From 6678ce6e2b26a3cb2b322455d7c9d850d95c1dc5 Mon Sep 17 00:00:00 2001 From: Alberto Balbo Date: Sun, 17 Aug 2025 23:15:06 +0200 Subject: [PATCH] Aggiornamenti significativi a BSHash e configurazioni MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modifiche principali: - Aggiornamento di App.config per il framework v4.8.1 e nuove impostazioni utente. - Aggiornamento di BSHash.csproj con nuovi riferimenti a librerie NuGet. - Introduzione di logica per la gestione degli utenti e delle credenziali in Database.cs. - Aggiunta di funzionalità di logging avanzate in Logger.cs. - Implementazione di un gestore API in Network.cs per inviare e ricevere dati hash. - Nuovi metodi per la gestione di file in Storage.cs con logging dettagliato. - Introduzione di classi come ApiManager, UserSession, CredentialManager e FileScanner. - Miglioramenti all'interfaccia utente per la gestione delle impostazioni del database e del login. - Rimozione di codice obsoleto per semplificare e migliorare la manutenzione. --- BSHash/BSHash/App.config | 196 ++++- BSHash/BSHash/BSHash.csproj | 170 ++++- BSHash/BSHash/Calculator.cs | 44 -- BSHash/BSHash/Database.cs | 242 ------ BSHash/BSHash/Forms/DatabaseSettingsForm.cs | 303 ++++++++ BSHash/BSHash/Forms/LoginForm.cs | 319 ++++++++ BSHash/BSHash/Forms/MainForm.cs | 483 ++++++++++++ BSHash/BSHash/Logger.cs | 138 ---- BSHash/BSHash/Main.Designer.cs | 507 ------------- BSHash/BSHash/Main.cs | 330 --------- BSHash/BSHash/Manager/ApiManager.cs | 267 +++++++ BSHash/BSHash/Manager/Calculator.cs | 73 ++ BSHash/BSHash/Manager/CredentialManager.cs | 70 ++ BSHash/BSHash/Manager/Database.cs | 689 ++++++++++++++++++ BSHash/BSHash/Manager/FileScanner.cs | 426 +++++++++++ BSHash/BSHash/Manager/Logger.cs | 379 ++++++++++ BSHash/BSHash/Manager/Network.cs | 200 +++++ BSHash/BSHash/{ => Manager}/Storage.cs | 105 ++- BSHash/BSHash/Network.cs | 99 --- BSHash/BSHash/Program.cs | 23 +- BSHash/BSHash/Properties/Settings.Designer.cs | 242 +++++- BSHash/BSHash/Properties/Settings.settings | 60 +- BSHash/BSHash/packages.config | 45 ++ 23 files changed, 3993 insertions(+), 1417 deletions(-) delete mode 100644 BSHash/BSHash/Calculator.cs delete mode 100644 BSHash/BSHash/Database.cs create mode 100644 BSHash/BSHash/Forms/DatabaseSettingsForm.cs create mode 100644 BSHash/BSHash/Forms/LoginForm.cs create mode 100644 BSHash/BSHash/Forms/MainForm.cs delete mode 100644 BSHash/BSHash/Logger.cs delete mode 100644 BSHash/BSHash/Main.Designer.cs delete mode 100644 BSHash/BSHash/Main.cs create mode 100644 BSHash/BSHash/Manager/ApiManager.cs create mode 100644 BSHash/BSHash/Manager/Calculator.cs create mode 100644 BSHash/BSHash/Manager/CredentialManager.cs create mode 100644 BSHash/BSHash/Manager/Database.cs create mode 100644 BSHash/BSHash/Manager/FileScanner.cs create mode 100644 BSHash/BSHash/Manager/Logger.cs create mode 100644 BSHash/BSHash/Manager/Network.cs rename BSHash/BSHash/{ => Manager}/Storage.cs (81%) delete mode 100644 BSHash/BSHash/Network.cs create mode 100644 BSHash/BSHash/packages.config diff --git a/BSHash/BSHash/App.config b/BSHash/BSHash/App.config index 583c63d..2874a46 100644 --- a/BSHash/BSHash/App.config +++ b/BSHash/BSHash/App.config @@ -1,30 +1,204 @@ - + -
+
- + + + + + + localhost + + + HashKeeperPro + + + sa + + + + + + 1433 + + + SQL Server + + + + + + False + + + 60 + + + https://api.hashkeeper.com/v1/hashes + + + + + + False + + + 100 + + + False + + + True + + + + + + False + + + + - + - - - - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BSHash/BSHash/BSHash.csproj b/BSHash/BSHash/BSHash.csproj index 2ed6cbf..76081cf 100644 --- a/BSHash/BSHash/BSHash.csproj +++ b/BSHash/BSHash/BSHash.csproj @@ -8,11 +8,12 @@ WinExe BSHash BSHash - v4.8 + v4.8.1 512 true true - + + AnyCPU @@ -34,8 +35,141 @@ 4 + + ..\packages\Azure.Core.1.46.2\lib\net472\Azure.Core.dll + + + ..\packages\Azure.Identity.1.14.1\lib\netstandard2.0\Azure.Identity.dll + + + ..\packages\MaterialSkin.2.2.3.1\lib\net48\MaterialSkin.dll + + + ..\packages\Microsoft.Bcl.AsyncInterfaces.10.0.0-preview.5.25277.114\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + ..\packages\Microsoft.Bcl.Cryptography.10.0.0-preview.5.25277.114\lib\net462\Microsoft.Bcl.Cryptography.dll + + + ..\packages\Microsoft.Bcl.TimeProvider.10.0.0-preview.5.25277.114\lib\net462\Microsoft.Bcl.TimeProvider.dll + + + ..\packages\Microsoft.Data.SqlClient.6.1.0-preview2.25178.5\lib\net462\Microsoft.Data.SqlClient.dll + + + ..\packages\Microsoft.Data.Sqlite.Core.9.0.7\lib\netstandard2.0\Microsoft.Data.Sqlite.dll + + + ..\packages\Microsoft.Extensions.Caching.Abstractions.10.0.0-preview.5.25277.114\lib\net462\Microsoft.Extensions.Caching.Abstractions.dll + + + ..\packages\Microsoft.Extensions.Caching.Memory.10.0.0-preview.5.25277.114\lib\net462\Microsoft.Extensions.Caching.Memory.dll + + + ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.10.0.0-preview.5.25277.114\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + ..\packages\Microsoft.Extensions.Logging.Abstractions.10.0.0-preview.5.25277.114\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll + + + ..\packages\Microsoft.Extensions.Options.10.0.0-preview.5.25277.114\lib\net462\Microsoft.Extensions.Options.dll + + + ..\packages\Microsoft.Extensions.Primitives.10.0.0-preview.5.25277.114\lib\net462\Microsoft.Extensions.Primitives.dll + + + ..\packages\Microsoft.Identity.Client.4.73.1\lib\net472\Microsoft.Identity.Client.dll + + + ..\packages\Microsoft.Identity.Client.Extensions.Msal.4.73.1\lib\netstandard2.0\Microsoft.Identity.Client.Extensions.Msal.dll + + + ..\packages\Microsoft.IdentityModel.Abstractions.8.12.1\lib\net472\Microsoft.IdentityModel.Abstractions.dll + + + ..\packages\Microsoft.IdentityModel.JsonWebTokens.8.12.1\lib\net472\Microsoft.IdentityModel.JsonWebTokens.dll + + + ..\packages\Microsoft.IdentityModel.Logging.8.12.1\lib\net472\Microsoft.IdentityModel.Logging.dll + + + ..\packages\Microsoft.IdentityModel.Protocols.8.12.1\lib\net472\Microsoft.IdentityModel.Protocols.dll + + + ..\packages\Microsoft.IdentityModel.Protocols.OpenIdConnect.8.12.1\lib\net472\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll + + + ..\packages\Microsoft.IdentityModel.Tokens.8.12.1\lib\net472\Microsoft.IdentityModel.Tokens.dll + + + ..\packages\SQLitePCLRaw.core.2.1.10\lib\netstandard2.0\SQLitePCLRaw.core.dll + + + ..\packages\System.Buffers.4.6.1\lib\net462\System.Buffers.dll + + + ..\packages\System.ClientModel.1.5.0-beta.1\lib\netstandard2.0\System.ClientModel.dll + + + + ..\packages\System.Data.Common.4.3.0\lib\net451\System.Data.Common.dll + True + True + + + + ..\packages\System.Diagnostics.DiagnosticSource.10.0.0-preview.5.25277.114\lib\net462\System.Diagnostics.DiagnosticSource.dll + + + ..\packages\System.Formats.Asn1.10.0.0-preview.5.25277.114\lib\net462\System.Formats.Asn1.dll + + + + ..\packages\System.IdentityModel.Tokens.Jwt.8.12.1\lib\net472\System.IdentityModel.Tokens.Jwt.dll + + + ..\packages\System.IO.FileSystem.AccessControl.5.0.0\lib\net461\System.IO.FileSystem.AccessControl.dll + + + ..\packages\System.IO.Pipelines.10.0.0-preview.5.25277.114\lib\net462\System.IO.Pipelines.dll + + + ..\packages\System.Memory.4.6.3\lib\net462\System.Memory.dll + + + ..\packages\System.Memory.Data.10.0.0-preview.5.25277.114\lib\net462\System.Memory.Data.dll + + + + ..\packages\System.Numerics.Vectors.4.6.1\lib\net462\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.1.2\lib\net462\System.Runtime.CompilerServices.Unsafe.dll + + + + ..\packages\System.Security.AccessControl.6.0.1\lib\net461\System.Security.AccessControl.dll + + + ..\packages\System.Security.Cryptography.Pkcs.10.0.0-preview.5.25277.114\lib\net462\System.Security.Cryptography.Pkcs.dll + + + ..\packages\System.Security.Cryptography.ProtectedData.10.0.0-preview.5.25277.114\lib\net462\System.Security.Cryptography.ProtectedData.dll + + + ..\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll + + + ..\packages\System.Text.Encodings.Web.10.0.0-preview.5.25277.114\lib\net462\System.Text.Encodings.Web.dll + + + ..\packages\System.Text.Json.10.0.0-preview.5.25277.114\lib\net462\System.Text.Json.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.6.3\lib\net462\System.Threading.Tasks.Extensions.dll + @@ -47,11 +181,23 @@ - - - - - + + Form + + + Form + + + Form + + + + + + + + + Form @@ -72,6 +218,7 @@ True Resources.resx + SettingsSingleFileGenerator Settings.Designer.cs @@ -86,4 +233,13 @@ + + + + Questo progetto fa riferimento a uno o più pacchetti NuGet che non sono presenti in questo computer. Usare lo strumento di ripristino dei pacchetti NuGet per scaricarli. Per altre informazioni, vedere http://go.microsoft.com/fwlink/?LinkID=322105. Il file mancante è {0}. + + + + + \ No newline at end of file diff --git a/BSHash/BSHash/Calculator.cs b/BSHash/BSHash/Calculator.cs deleted file mode 100644 index c7c0e2a..0000000 --- a/BSHash/BSHash/Calculator.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Security.Cryptography; -using System.Windows.Forms; - -namespace BSHash -{ - public class Calculator - { - private Logger _logger; - - public Calculator(Logger logger) - { - _logger = logger; - } - - public string CalculateHash(string filePath) - { - try - { - using (SHA256 sha256 = SHA256.Create()) - { - using (FileStream fileStream = File.OpenRead(filePath)) - { - byte[] hashBytes = sha256.ComputeHash(fileStream); - string hash = BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant(); - - _logger.Log("Hash " + hash + " calcolato per il file " + filePath.ToString(), LogType.INFO); - - return hash; - } - } - } - catch (Exception ex) - { - // Log the exception or handle it as needed - _logger.Log("Errore nella lettura o hash del file " + filePath.ToString() + ".\nErrore: " + ex.Message.ToString(), LogType.ERROR); - - return null; - } - } - } -} diff --git a/BSHash/BSHash/Database.cs b/BSHash/BSHash/Database.cs deleted file mode 100644 index 1ddae0b..0000000 --- a/BSHash/BSHash/Database.cs +++ /dev/null @@ -1,242 +0,0 @@ -using System; -using System.Data; -using System.Data.SqlClient; - -namespace BSHash -{ - public class Database - { - private readonly string _connectionString; - - public Database() - { - string serverstring = Properties.Settings.Default.Server; - string databasestring = Properties.Settings.Default.Database; - string userstring = Properties.Settings.Default.User; - string passwordstring = Properties.Settings.Default.Password; - - // Ricompongo la stringa di connessione - _connectionString = $"Server={serverstring};Database={databasestring};User Id={userstring};Password={passwordstring};"; - } - - public bool ClearHash() - { - using (SqlConnection connection = new SqlConnection(_connectionString)) - { - connection.Open(); - using (SqlTransaction transaction = connection.BeginTransaction()) - { - try - { - // Delete all rows from the Hash table - string deleteQuery = "DELETE FROM Hash"; - using (SqlCommand deleteCommand = new SqlCommand(deleteQuery, connection, transaction)) - { - deleteCommand.ExecuteNonQuery(); - } - - transaction.Commit(); - return true; - } - catch - { - transaction.Rollback(); - return false; - throw; - } - } - } - } - - public bool HashExists(string hash) - { - using (SqlConnection connection = new SqlConnection(_connectionString)) - { - try - { - connection.Open(); - - // Controlla se l'hash esiste già nel database - string checkQuery = "SELECT COUNT(*) FROM Hash WHERE Hash = (@Hash)"; - using (SqlCommand checkCommand = new SqlCommand(checkQuery, connection)) - { - checkCommand.Parameters.AddWithValue("@Hash", hash); - int count = (int)checkCommand.ExecuteScalar(); - - return count != 0; - } - } - catch - { - return true; - throw; - } - } - } - - public bool InsertHash(string path, string hash) - { - using (SqlConnection connection = new SqlConnection(_connectionString)) - { - connection.Open(); - using (SqlTransaction transaction = connection.BeginTransaction()) - { - try - { - // L'hash non esiste quindi lo inserisco - string insertQuery = "INSERT INTO Hash (Path, Hash) VALUES (@Path, @Hash)"; - using (SqlCommand insertCommand = new SqlCommand(insertQuery, connection, transaction)) - { - insertCommand.Parameters.AddWithValue("@Path", path); - insertCommand.Parameters.AddWithValue("@Hash", hash); - insertCommand.ExecuteNonQuery(); - } - - transaction.Commit(); - - return true; - } - catch - { - transaction.Rollback(); - return false; - throw; - } - } - } - } - - public bool UpdateHash(string path, string hash) - { - using (SqlConnection connection = new SqlConnection(_connectionString)) - { - connection.Open(); - using (SqlTransaction transaction = connection.BeginTransaction()) - { - try - { - // L'hash esiste quindi aggiorno la data di ultima scansione - string updateQuery = "UPDATE Hash SET Path = (@Path) WHERE Hash = (@Hash)"; - using (SqlCommand updateCommand = new SqlCommand(updateQuery, connection, transaction)) - { - updateCommand.Parameters.AddWithValue("@Path", path); - updateCommand.Parameters.AddWithValue("@Hash", hash); - updateCommand.ExecuteNonQuery(); - } - - transaction.Commit(); - - return true; - } - catch - { - transaction.Rollback(); - - return false; - throw; - } - } - } - } - - public bool InsertHistory(string hash) - { - using (SqlConnection connection = new SqlConnection(_connectionString)) - { - connection.Open(); - using (SqlTransaction transaction = connection.BeginTransaction()) - { - try - { - - // L'hash esiste quindi aggiorno la data di ultima scansione - string updateQuery = "INSERT INTO History (Hash) VALUES (@Hash)"; - using (SqlCommand updateCommand = new SqlCommand(updateQuery, connection, transaction)) - { - updateCommand.Parameters.AddWithValue("@Hash", hash); - updateCommand.ExecuteNonQuery(); - } - - transaction.Commit(); - - return true; - } - catch - { - transaction.Rollback(); - - return false; - throw; - } - } - } - } - - public void InsertLog(string message, LogType type = LogType.INFO) - { - using (SqlConnection connection = new SqlConnection(_connectionString)) - { - connection.Open(); - using (SqlTransaction transaction = connection.BeginTransaction()) - { - try - { - string query = "INSERT INTO Log (Message, Type) VALUES (@Message, @Type)"; - using (SqlCommand command = new SqlCommand(query, connection, transaction)) - { - command.Parameters.AddWithValue("@Message", message); - command.Parameters.AddWithValue("@Type", type); - command.ExecuteNonQuery(); - } - transaction.Commit(); - } - catch - { - transaction.Rollback(); - throw; - } - } - } - } - - public DataTable GetHashes() - { - DataTable hashes = new DataTable(); - - using (SqlConnection connection = new SqlConnection(_connectionString)) - { - string query = "SELECT * FROM Hash"; - - using (SqlCommand command = new SqlCommand(query, connection)) - { - connection.Open(); - using (SqlDataReader reader = command.ExecuteReader()) - { - hashes.Load(reader); - } - } - } - - return hashes; - } - - public DataTable GetLogs(string query) - { - DataTable logs = new DataTable(); - - using (SqlConnection connection = new SqlConnection(_connectionString)) - { - using (SqlCommand command = new SqlCommand(query, connection)) - { - connection.Open(); - using (SqlDataReader reader = command.ExecuteReader()) - { - logs.Load(reader); - } - } - } - - return logs; - } - } -} diff --git a/BSHash/BSHash/Forms/DatabaseSettingsForm.cs b/BSHash/BSHash/Forms/DatabaseSettingsForm.cs new file mode 100644 index 0000000..43a529e --- /dev/null +++ b/BSHash/BSHash/Forms/DatabaseSettingsForm.cs @@ -0,0 +1,303 @@ +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace BSHash +{ + public partial class DatabaseSettingsForm : Form + { + private TextBox txtServer; + private TextBox txtDatabase; + private TextBox txtUsername; + private TextBox txtPassword; + private TextBox txtPort; + private ComboBox cmbProvider; + private Button btnSave; + private Button btnCancel; + private Button btnTest; + private Label lblStatus; + + public DatabaseSettingsForm() + { + InitializeComponent(); + LoadSettings(); + } + + private void InitializeComponent() + { + this.Size = new Size(500, 450); + this.Text = "Impostazioni Database"; + this.StartPosition = FormStartPosition.CenterParent; + this.FormBorderStyle = FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.BackColor = Color.FromArgb(248, 249, 250); + + // Provider + var lblProvider = new Label + { + Text = "Provider Database:", + Location = new Point(20, 20), + Size = new Size(120, 20), + Font = new Font("Segoe UI", 9) + }; + + cmbProvider = new ComboBox + { + Location = new Point(150, 18), + Size = new Size(300, 25), + DropDownStyle = ComboBoxStyle.DropDownList, + Font = new Font("Segoe UI", 9) + }; + cmbProvider.Items.AddRange(new[] { "SQL Server", "MySQL", "PostgreSQL" }); + cmbProvider.SelectedIndex = 0; + + // Server + var lblServer = new Label + { + Text = "Server:", + Location = new Point(20, 60), + Size = new Size(120, 20), + Font = new Font("Segoe UI", 9) + }; + + txtServer = new TextBox + { + Location = new Point(150, 58), + Size = new Size(200, 25), + Font = new Font("Segoe UI", 9) + }; + + // Port + var lblPort = new Label + { + Text = "Porta:", + Location = new Point(360, 60), + Size = new Size(40, 20), + Font = new Font("Segoe UI", 9) + }; + + txtPort = new TextBox + { + Location = new Point(410, 58), + Size = new Size(60, 25), + Font = new Font("Segoe UI", 9) + }; + + // Database + var lblDatabase = new Label + { + Text = "Database:", + Location = new Point(20, 100), + Size = new Size(120, 20), + Font = new Font("Segoe UI", 9) + }; + + txtDatabase = new TextBox + { + Location = new Point(150, 98), + Size = new Size(300, 25), + Font = new Font("Segoe UI", 9) + }; + + // Username + var lblUsername = new Label + { + Text = "Username:", + Location = new Point(20, 140), + Size = new Size(120, 20), + Font = new Font("Segoe UI", 9) + }; + + txtUsername = new TextBox + { + Location = new Point(150, 138), + Size = new Size(300, 25), + Font = new Font("Segoe UI", 9) + }; + + // Password + var lblPassword = new Label + { + Text = "Password:", + Location = new Point(20, 180), + Size = new Size(120, 20), + Font = new Font("Segoe UI", 9) + }; + + txtPassword = new TextBox + { + Location = new Point(150, 178), + Size = new Size(300, 25), + Font = new Font("Segoe UI", 9), + UseSystemPasswordChar = true + }; + + // Status + lblStatus = new Label + { + Location = new Point(20, 220), + Size = new Size(450, 40), + Font = new Font("Segoe UI", 9), + ForeColor = Color.FromArgb(107, 114, 128) + }; + + // Buttons + btnTest = new Button + { + Text = "Testa Connessione", + Location = new Point(20, 280), + Size = new Size(140, 35), + Font = new Font("Segoe UI", 9), + BackColor = Color.FromArgb(99, 102, 241), + ForeColor = Color.White, + FlatStyle = FlatStyle.Flat + }; + btnTest.FlatAppearance.BorderSize = 0; + btnTest.Click += BtnTest_Click; + + btnCancel = new Button + { + Text = "Annulla", + Location = new Point(280, 330), + Size = new Size(80, 35), + Font = new Font("Segoe UI", 9), + BackColor = Color.FromArgb(107, 114, 128), + ForeColor = Color.White, + FlatStyle = FlatStyle.Flat + }; + btnCancel.FlatAppearance.BorderSize = 0; + btnCancel.Click += BtnCancel_Click; + + btnSave = new Button + { + Text = "Salva", + Location = new Point(370, 330), + Size = new Size(80, 35), + Font = new Font("Segoe UI", 9), + BackColor = Color.FromArgb(34, 197, 94), + ForeColor = Color.White, + FlatStyle = FlatStyle.Flat + }; + btnSave.FlatAppearance.BorderSize = 0; + btnSave.Click += BtnSave_Click; + + // Add controls + this.Controls.AddRange(new Control[] + { + lblProvider, cmbProvider, + lblServer, txtServer, lblPort, txtPort, + lblDatabase, txtDatabase, + lblUsername, txtUsername, + lblPassword, txtPassword, + lblStatus, + btnTest, btnCancel, btnSave + }); + } + + private async void BtnTest_Click(object sender, EventArgs e) + { + try + { + btnTest.Enabled = false; + lblStatus.Text = "Testando connessione..."; + lblStatus.ForeColor = Color.Blue; + + var database = new BSHash.Manager.Database(); + bool success = await database.TestConnectionAsync(GetConnectionString()); + + if (success) + { + lblStatus.Text = "Connessione riuscita!"; + lblStatus.ForeColor = Color.Green; + } + else + { + lblStatus.Text = "Connessione fallita. Verificare i parametri."; + lblStatus.ForeColor = Color.Red; + } + } + catch (Exception ex) + { + lblStatus.Text = $"Errore: {ex.Message}"; + lblStatus.ForeColor = Color.Red; + } + finally + { + btnTest.Enabled = true; + } + } + + private void BtnSave_Click(object sender, EventArgs e) + { + try + { + SaveSettings(); + lblStatus.Text = "Impostazioni salvate!"; + lblStatus.ForeColor = Color.Green; + + // Close form after brief delay + Timer timer = new Timer(); + timer.Interval = 1000; + timer.Tick += (s, args) => { timer.Stop(); this.Close(); }; + timer.Start(); + } + catch (Exception ex) + { + lblStatus.Text = $"Errore nel salvataggio: {ex.Message}"; + lblStatus.ForeColor = Color.Red; + } + } + + private void BtnCancel_Click(object sender, EventArgs e) + { + this.Close(); + } + + private void LoadSettings() + { + txtServer.Text = Properties.Settings.Default.DatabaseServer; + txtDatabase.Text = Properties.Settings.Default.DatabaseName; + txtUsername.Text = Properties.Settings.Default.DatabaseUser; + txtPassword.Text = Properties.Settings.Default.DatabasePassword; + txtPort.Text = Properties.Settings.Default.DatabasePort.ToString(); + cmbProvider.Text = Properties.Settings.Default.DatabaseProvider; + } + + private void SaveSettings() + { + Properties.Settings.Default.DatabaseServer = txtServer.Text; + Properties.Settings.Default.DatabaseName = txtDatabase.Text; + Properties.Settings.Default.DatabaseUser = txtUsername.Text; + Properties.Settings.Default.DatabasePassword = txtPassword.Text; + + if (int.TryParse(txtPort.Text, out int port)) + Properties.Settings.Default.DatabasePort = port; + + Properties.Settings.Default.DatabaseProvider = cmbProvider.Text; + Properties.Settings.Default.Save(); + } + + private string GetConnectionString() + { + string provider = cmbProvider.Text; + string server = txtServer.Text; + string database = txtDatabase.Text; + string username = txtUsername.Text; + string password = txtPassword.Text; + string port = txtPort.Text; + + switch (provider) + { + case "SQL Server": + return $"Server={server},{port};Database={database};User Id={username};Password={password};"; + case "MySQL": + return $"Server={server};Port={port};Database={database};Uid={username};Pwd={password};"; + case "PostgreSQL": + return $"Host={server};Port={port};Database={database};Username={username};Password={password};"; + default: + return $"Server={server};Database={database};User Id={username};Password={password};"; + } + } + } +} \ No newline at end of file diff --git a/BSHash/BSHash/Forms/LoginForm.cs b/BSHash/BSHash/Forms/LoginForm.cs new file mode 100644 index 0000000..1087dd1 --- /dev/null +++ b/BSHash/BSHash/Forms/LoginForm.cs @@ -0,0 +1,319 @@ +using System; +using System.Drawing; +using System.Threading.Tasks; +using System.Windows.Forms; +using BSHash.Manager; + +namespace BSHash +{ + public partial class LoginForm : Form + { + private TextBox txtUsername; + private TextBox txtPassword; + private CheckBox chkRememberCredentials; + private Button btnLogin; + private Button btnDatabaseSettings; + private Label lblTitle; + private Label lblUsername; + private Label lblPassword; + private Label lblStatus; + private ProgressBar progressBar; + private PictureBox pictureBoxLogo; + private Panel panelMain; + + private Database database; + + public LoginForm() + { + InitializeComponent(); + LoadRememberedCredentials(); + database = new Database(); + } + + private void InitializeComponent() + { + this.Size = new Size(500, 600); + this.Text = "HashKeeper Pro - Login"; + this.StartPosition = FormStartPosition.CenterScreen; + this.FormBorderStyle = FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.BackColor = Color.FromArgb(248, 249, 250); + + // Main panel + panelMain = new Panel + { + Size = new Size(400, 500), + Location = new Point((this.Width - 400) / 2, (this.Height - 500) / 2), + BackColor = Color.White, + BorderStyle = BorderStyle.None + }; + + // Logo + pictureBoxLogo = new PictureBox + { + Size = new Size(64, 64), + Location = new Point((panelMain.Width - 64) / 2, 40), + BackColor = Color.FromArgb(59, 130, 246), + SizeMode = PictureBoxSizeMode.CenterImage + }; + + // Title + lblTitle = new Label + { + Text = "ACCEDI", + Font = new Font("Segoe UI", 24, FontStyle.Bold), + Location = new Point((panelMain.Width - 150) / 2, 130), + Size = new Size(150, 40), + TextAlign = ContentAlignment.MiddleCenter, + ForeColor = Color.FromArgb(31, 41, 55) + }; + + // Username label + lblUsername = new Label + { + Text = "Nome Utente", + Font = new Font("Segoe UI", 9), + Location = new Point(50, 200), + Size = new Size(100, 20), + ForeColor = Color.FromArgb(107, 114, 128) + }; + + // Username textbox + txtUsername = new TextBox + { + Location = new Point(50, 225), + Size = new Size(300, 35), + Font = new Font("Segoe UI", 11), + BorderStyle = BorderStyle.FixedSingle, + BackColor = Color.White + }; + + // Password label + lblPassword = new Label + { + Text = "Password", + Font = new Font("Segoe UI", 9), + Location = new Point(50, 270), + Size = new Size(100, 20), + ForeColor = Color.FromArgb(107, 114, 128) + }; + + // Password textbox + txtPassword = new TextBox + { + Location = new Point(50, 295), + Size = new Size(300, 35), + Font = new Font("Segoe UI", 11), + BorderStyle = BorderStyle.FixedSingle, + UseSystemPasswordChar = true, + BackColor = Color.White + }; + + // Remember credentials checkbox + chkRememberCredentials = new CheckBox + { + Text = "Ricorda Credenziali", + Location = new Point(50, 340), + Size = new Size(150, 20), + Font = new Font("Segoe UI", 9), + ForeColor = Color.FromArgb(107, 114, 128) + }; + + // Login button + btnLogin = new Button + { + Text = "Accedi", + Location = new Point(50, 380), + Size = new Size(300, 45), + Font = new Font("Segoe UI", 12, FontStyle.Bold), + BackColor = Color.FromArgb(59, 130, 246), + ForeColor = Color.White, + FlatStyle = FlatStyle.Flat, + Cursor = Cursors.Hand + }; + btnLogin.FlatAppearance.BorderSize = 0; + btnLogin.Click += BtnLogin_Click; + + // Status label + lblStatus = new Label + { + Location = new Point(50, 435), + Size = new Size(300, 20), + Font = new Font("Segoe UI", 9), + ForeColor = Color.FromArgb(107, 114, 128), + TextAlign = ContentAlignment.MiddleCenter + }; + + // Progress bar + progressBar = new ProgressBar + { + Location = new Point(50, 460), + Size = new Size(300, 5), + Style = ProgressBarStyle.Marquee, + Visible = false + }; + + // Database settings button + btnDatabaseSettings = new Button + { + Size = new Size(30, 30), + Location = new Point(this.Width - 50, this.Height - 50), + Text = "?", + Font = new Font("Segoe UI", 12), + BackColor = Color.Transparent, + FlatStyle = FlatStyle.Flat, + ForeColor = Color.FromArgb(107, 114, 128), + Cursor = Cursors.Hand + }; + btnDatabaseSettings.FlatAppearance.BorderSize = 0; + btnDatabaseSettings.Click += BtnDatabaseSettings_Click; + + // Add controls + panelMain.Controls.AddRange(new Control[] + { + pictureBoxLogo, lblTitle, lblUsername, txtUsername, + lblPassword, txtPassword, chkRememberCredentials, + btnLogin, lblStatus, progressBar + }); + + this.Controls.Add(panelMain); + this.Controls.Add(btnDatabaseSettings); + + // Set tab order + txtUsername.TabIndex = 0; + txtPassword.TabIndex = 1; + chkRememberCredentials.TabIndex = 2; + btnLogin.TabIndex = 3; + + // Set default button + this.AcceptButton = btnLogin; + } + + private async void BtnLogin_Click(object sender, EventArgs e) + { + if (string.IsNullOrWhiteSpace(txtUsername.Text) || string.IsNullOrWhiteSpace(txtPassword.Text)) + { + ShowStatus("Inserire nome utente e password.", Color.Red); + return; + } + + SetControlsEnabled(false); + ShowStatus("Connessione al database...", Color.Blue); + progressBar.Visible = true; + + try + { + // Test database connection + if (!await database.TestConnectionAsync()) + { + ShowStatus("Errore di connessione al database. Verificare le impostazioni.", Color.Red); + return; + } + + ShowStatus("Verifica struttura database...", Color.Blue); + + // Ensure database schema + await database.EnsureDatabaseSchemaAsync(); + + ShowStatus("Autenticazione utente...", Color.Blue); + + // Authenticate user + bool loginSuccess = await database.AuthenticateUserAsync(txtUsername.Text, txtPassword.Text); + + if (loginSuccess) + { + // Save credentials if requested + if (chkRememberCredentials.Checked) + { + SaveCredentials(); + } + + // Log successful login + await database.LogEventAsync("Login", "Accesso effettuato con successo", Manager.LogType.INFO, txtUsername.Text); + + ShowStatus("Login effettuato con successo!", Color.Green); + + // Store current user + UserSession.CurrentUser = txtUsername.Text; + + await Task.Delay(500); // Brief delay for user feedback + this.DialogResult = DialogResult.OK; + } + else + { + ShowStatus("Credenziali non valide.", Color.Red); + await database.LogEventAsync("Login", "Tentativo di accesso fallito", Manager.LogType.ERROR, txtUsername.Text); + } + } + catch (Exception ex) + { + ShowStatus($"Errore durante il login: {ex.Message}", Color.Red); + await database.LogEventAsync("Login", $"Errore durante il login: {ex.Message}", Manager.LogType.ERROR, txtUsername.Text); + } + finally + { + SetControlsEnabled(true); + progressBar.Visible = false; + } + } + + private void BtnDatabaseSettings_Click(object sender, EventArgs e) + { + using (var settingsForm = new DatabaseSettingsForm()) + { + settingsForm.ShowDialog(); + } + } + + private void SetControlsEnabled(bool enabled) + { + txtUsername.Enabled = enabled; + txtPassword.Enabled = enabled; + chkRememberCredentials.Enabled = enabled; + btnLogin.Enabled = enabled; + btnDatabaseSettings.Enabled = enabled; + } + + private void ShowStatus(string message, Color color) + { + lblStatus.Text = message; + lblStatus.ForeColor = color; + } + + private void LoadRememberedCredentials() + { + try + { + var credentials = CredentialManager.LoadCredentials(); + if (credentials != null) + { + txtUsername.Text = credentials.Username; + txtPassword.Text = credentials.Password; + chkRememberCredentials.Checked = true; + } + } + catch + { + // Ignore errors loading credentials + } + } + + private void SaveCredentials() + { + try + { + CredentialManager.SaveCredentials(txtUsername.Text, txtPassword.Text); + } + catch + { + // Ignore errors saving credentials + } + } + } + + // Simple user session class + public static class UserSession + { + public static string CurrentUser { get; set; } + } +} \ No newline at end of file diff --git a/BSHash/BSHash/Forms/MainForm.cs b/BSHash/BSHash/Forms/MainForm.cs new file mode 100644 index 0000000..3c19769 --- /dev/null +++ b/BSHash/BSHash/Forms/MainForm.cs @@ -0,0 +1,483 @@ +using System; +using System.Drawing; +using System.Windows.Forms; +using BSHash.Manager; + +namespace BSHash +{ + public partial class MainForm : Form + { + private Panel sidebarPanel; + private Panel contentPanel; + private Panel headerPanel; + private Label titleLabel; + private Button selectedNavButton; + + // Navigation buttons + private Button btnHome; + private Button btnPaths; + private Button btnScanStatus; + private Button btnHistory; + private Button btnSettings; + private Button btnLog; + private Button btnLogout; + + // Content panels + private Panel homePanel; + private Panel pathsPanel; + private Panel scanStatusPanel; + private Panel historyPanel; + private Panel settingsPanel; + private Panel logPanel; + + private FileScanner fileScanner; + private Database database; + private ApiManager apiManager; + + public MainForm() + { + InitializeComponent(); + InitializeManagers(); + ShowHomePanel(); + } + + private void InitializeComponent() + { + this.Size = new Size(1200, 800); + this.Text = "HashKeeper Pro"; + this.StartPosition = FormStartPosition.CenterScreen; + this.WindowState = FormWindowState.Maximized; + this.BackColor = Color.FromArgb(248, 249, 250); + + CreateSidebar(); + CreateHeader(); + CreateContentArea(); + CreateContentPanels(); + } + + private void CreateSidebar() + { + sidebarPanel = new Panel + { + Dock = DockStyle.Left, + Width = 250, + BackColor = Color.FromArgb(31, 41, 55), + Padding = new Padding(0, 20, 0, 20) + }; + + // Logo area + var logoPanel = new Panel + { + Height = 80, + Dock = DockStyle.Top, + BackColor = Color.Transparent + }; + + var logoLabel = new Label + { + Text = "HashKeeper Pro", + Font = new Font("Segoe UI", 16, FontStyle.Bold), + ForeColor = Color.White, + TextAlign = ContentAlignment.MiddleCenter, + Dock = DockStyle.Fill + }; + + logoPanel.Controls.Add(logoLabel); + sidebarPanel.Controls.Add(logoPanel); + + // Navigation buttons + CreateNavigationButtons(); + + this.Controls.Add(sidebarPanel); + } + + private void CreateNavigationButtons() + { + var navPanel = new Panel + { + Dock = DockStyle.Fill, + BackColor = Color.Transparent, + Padding = new Padding(10, 20, 10, 10) + }; + + // Home + btnHome = CreateNavButton("?? Home", 0); + btnHome.Click += (s, e) => ShowHomePanel(); + + // Paths + btnPaths = CreateNavButton("?? Percorsi", 1); + btnPaths.Click += (s, e) => ShowPathsPanel(); + + // Scan Status + btnScanStatus = CreateNavButton("?? Stato Scansioni", 2); + btnScanStatus.Click += (s, e) => ShowScanStatusPanel(); + + // History + btnHistory = CreateNavButton("?? Cronologia", 3); + btnHistory.Click += (s, e) => ShowHistoryPanel(); + + // Settings + btnSettings = CreateNavButton("?? Impostazioni", 4); + btnSettings.Click += (s, e) => ShowSettingsPanel(); + + // Log + btnLog = CreateNavButton("?? Log", 5); + btnLog.Click += (s, e) => ShowLogPanel(); + + // Logout (at bottom) + btnLogout = CreateNavButton("?? Logout", 10); + btnLogout.Click += BtnLogout_Click; + btnLogout.Dock = DockStyle.Bottom; + + navPanel.Controls.AddRange(new Control[] { btnHome, btnPaths, btnScanStatus, btnHistory, btnSettings, btnLog }); + sidebarPanel.Controls.Add(navPanel); + sidebarPanel.Controls.Add(btnLogout); + } + + private Button CreateNavButton(string text, int index) + { + var button = new Button + { + Text = text, + Height = 50, + Dock = DockStyle.Top, + FlatStyle = FlatStyle.Flat, + BackColor = Color.Transparent, + ForeColor = Color.FromArgb(209, 213, 219), + Font = new Font("Segoe UI", 10), + TextAlign = ContentAlignment.MiddleLeft, + Padding = new Padding(20, 0, 0, 0), + Margin = new Padding(0, 2, 0, 2), + Cursor = Cursors.Hand + }; + + button.FlatAppearance.BorderSize = 0; + button.FlatAppearance.MouseOverBackColor = Color.FromArgb(55, 65, 81); + + return button; + } + + private void CreateHeader() + { + headerPanel = new Panel + { + Dock = DockStyle.Top, + Height = 60, + BackColor = Color.White, + Padding = new Padding(20, 0, 20, 0) + }; + + titleLabel = new Label + { + Font = new Font("Segoe UI", 18, FontStyle.Bold), + ForeColor = Color.FromArgb(31, 41, 55), + BackColor = Color.Transparent, + Dock = DockStyle.Left, + AutoSize = true, + TextAlign = ContentAlignment.MiddleLeft + }; + + var userLabel = new Label + { + Text = $"Benvenuto, {UserSession.CurrentUser}", + Font = new Font("Segoe UI", 10), + ForeColor = Color.FromArgb(107, 114, 128), + Dock = DockStyle.Right, + AutoSize = true, + TextAlign = ContentAlignment.MiddleRight + }; + + headerPanel.Controls.Add(titleLabel); + headerPanel.Controls.Add(userLabel); + this.Controls.Add(headerPanel); + } + + private void CreateContentArea() + { + contentPanel = new Panel + { + Dock = DockStyle.Fill, + BackColor = Color.FromArgb(248, 249, 250), + Padding = new Padding(20) + }; + + this.Controls.Add(contentPanel); + } + + private void CreateContentPanels() + { + // Create all content panels but hide them initially + homePanel = CreateHomePanel(); + pathsPanel = CreatePathsPanel(); + scanStatusPanel = CreateScanStatusPanel(); + historyPanel = CreateHistoryPanel(); + settingsPanel = CreateSettingsPanel(); + logPanel = CreateLogPanel(); + + contentPanel.Controls.AddRange(new Control[] + { + homePanel, pathsPanel, scanStatusPanel, + historyPanel, settingsPanel, logPanel + }); + + // Hide all panels initially + foreach (Control panel in contentPanel.Controls) + panel.Visible = false; + } + + private Panel CreateHomePanel() + { + var panel = new Panel { Dock = DockStyle.Fill }; + + // Dashboard cards + var statsPanel = new FlowLayoutPanel + { + Dock = DockStyle.Top, + Height = 120, + FlowDirection = FlowDirection.LeftToRight, + WrapContents = false, + Padding = new Padding(0, 0, 0, 20) + }; + + // Total Hashes card + var totalHashesCard = CreateDashboardCard("Hash Totali", "0", Color.FromArgb(59, 130, 246)); + var newHashesCard = CreateDashboardCard("Nuovi Hash", "0", Color.FromArgb(34, 197, 94)); + var sentHashesCard = CreateDashboardCard("Hash Inviati", "0", Color.FromArgb(168, 85, 247)); + var confirmedHashesCard = CreateDashboardCard("Hash Confermati", "0", Color.FromArgb(245, 158, 11)); + + statsPanel.Controls.AddRange(new Control[] { totalHashesCard, newHashesCard, sentHashesCard, confirmedHashesCard }); + + // Recent activity + var activityPanel = new Panel + { + Dock = DockStyle.Fill, + BackColor = Color.White, + Padding = new Padding(20) + }; + + var activityLabel = new Label + { + Text = "Attività Recente", + Font = new Font("Segoe UI", 14, FontStyle.Bold), + Dock = DockStyle.Top, + Height = 30 + }; + + var activityList = new ListBox + { + Dock = DockStyle.Fill, + Font = new Font("Segoe UI", 10), + BorderStyle = BorderStyle.None + }; + + activityPanel.Controls.Add(activityLabel); + activityPanel.Controls.Add(activityList); + + panel.Controls.Add(statsPanel); + panel.Controls.Add(activityPanel); + + return panel; + } + + private Panel CreateDashboardCard(string title, string value, Color color) + { + var card = new Panel + { + Size = new Size(200, 100), + BackColor = Color.White, + Margin = new Padding(0, 0, 20, 0) + }; + + var colorBar = new Panel + { + Height = 4, + Dock = DockStyle.Top, + BackColor = color + }; + + var titleLabel = new Label + { + Text = title, + Font = new Font("Segoe UI", 10), + ForeColor = Color.FromArgb(107, 114, 128), + Location = new Point(15, 15), + AutoSize = true + }; + + var valueLabel = new Label + { + Text = value, + Font = new Font("Segoe UI", 24, FontStyle.Bold), + ForeColor = Color.FromArgb(31, 41, 55), + Location = new Point(15, 40), + AutoSize = true + }; + + card.Controls.Add(colorBar); + card.Controls.Add(titleLabel); + card.Controls.Add(valueLabel); + + return card; + } + + private Panel CreatePathsPanel() + { + var panel = new Panel { Dock = DockStyle.Fill }; + + var label = new Label + { + Text = "Gestione Percorsi - In sviluppo", + Font = new Font("Segoe UI", 16), + Dock = DockStyle.Fill, + TextAlign = ContentAlignment.MiddleCenter + }; + + panel.Controls.Add(label); + return panel; + } + + private Panel CreateScanStatusPanel() + { + var panel = new Panel { Dock = DockStyle.Fill }; + + var label = new Label + { + Text = "Stato Scansioni - In sviluppo", + Font = new Font("Segoe UI", 16), + Dock = DockStyle.Fill, + TextAlign = ContentAlignment.MiddleCenter + }; + + panel.Controls.Add(label); + return panel; + } + + private Panel CreateHistoryPanel() + { + var panel = new Panel { Dock = DockStyle.Fill }; + + var label = new Label + { + Text = "Cronologia - In sviluppo", + Font = new Font("Segoe UI", 16), + Dock = DockStyle.Fill, + TextAlign = ContentAlignment.MiddleCenter + }; + + panel.Controls.Add(label); + return panel; + } + + private Panel CreateSettingsPanel() + { + var panel = new Panel { Dock = DockStyle.Fill }; + + var label = new Label + { + Text = "Impostazioni - In sviluppo", + Font = new Font("Segoe UI", 16), + Dock = DockStyle.Fill, + TextAlign = ContentAlignment.MiddleCenter + }; + + panel.Controls.Add(label); + return panel; + } + + private Panel CreateLogPanel() + { + var panel = new Panel { Dock = DockStyle.Fill }; + + var label = new Label + { + Text = "Log - In sviluppo", + Font = new Font("Segoe UI", 16), + Dock = DockStyle.Fill, + TextAlign = ContentAlignment.MiddleCenter + }; + + panel.Controls.Add(label); + return panel; + } + + private void ShowPanel(Panel panelToShow, Button navButton, string title) + { + // Hide all panels + foreach (Control panel in contentPanel.Controls) + panel.Visible = false; + + // Show selected panel + panelToShow.Visible = true; + + // Update navigation button appearance + if (selectedNavButton != null) + { + selectedNavButton.BackColor = Color.Transparent; + selectedNavButton.ForeColor = Color.FromArgb(209, 213, 219); + } + + selectedNavButton = navButton; + navButton.BackColor = Color.FromArgb(59, 130, 246); + navButton.ForeColor = Color.White; + + // Update title + titleLabel.Text = title; + } + + private void ShowHomePanel() + { + ShowPanel(homePanel, btnHome, "Dashboard"); + } + + private void ShowPathsPanel() + { + ShowPanel(pathsPanel, btnPaths, "Gestione Percorsi"); + } + + private void ShowScanStatusPanel() + { + ShowPanel(scanStatusPanel, btnScanStatus, "Stato Scansioni"); + } + + private void ShowHistoryPanel() + { + ShowPanel(historyPanel, btnHistory, "Cronologia"); + } + + private void ShowSettingsPanel() + { + ShowPanel(settingsPanel, btnSettings, "Impostazioni"); + } + + private void ShowLogPanel() + { + ShowPanel(logPanel, btnLog, "Log Sistema"); + } + + private void BtnLogout_Click(object sender, EventArgs e) + { + var result = MessageBox.Show("Sei sicuro di voler uscire?", "Conferma Logout", + MessageBoxButtons.YesNo, MessageBoxIcon.Question); + + if (result == DialogResult.Yes) + { + UserSession.CurrentUser = null; + this.Close(); + } + } + + private void InitializeManagers() + { + database = new Database(); + fileScanner = new FileScanner(database); + apiManager = new ApiManager(database); + } + + protected override void OnFormClosing(FormClosingEventArgs e) + { + // Stop any running operations + fileScanner?.StopAllScans(); + base.OnFormClosing(e); + } + } +} \ No newline at end of file diff --git a/BSHash/BSHash/Logger.cs b/BSHash/BSHash/Logger.cs deleted file mode 100644 index ea23d30..0000000 --- a/BSHash/BSHash/Logger.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; -using static System.Windows.Forms.VisualStyles.VisualStyleElement; - -namespace BSHash -{ - public enum LogType - { - INFO, - DEBUG, - WARN, - ERROR, - FATAL, - TEST - } - - public enum LogStatus - { - ATTESA, - PREPARAZIONE, - ELABORAZIONE, - FERMATA, - COMPLETATO, - ERRORE - } - - public class Logger - { - private Database databaseHelper; - private System.Windows.Forms.TextBox logTextBox; - - public Logger(System.Windows.Forms.TextBox logTextBox, Database databaseHelper) - { - this.logTextBox = logTextBox; - this.databaseHelper = databaseHelper; - } - - public void Log(string message, LogType type = LogType.INFO) - { - databaseHelper.InsertLog(message, type); - } - - public void LogEsecuzioneExecute(LogStatus stato, long spazioscansionato, long scansionati, int errori, int warning) - { - StringBuilder log = new StringBuilder(); - - log.Append("Stato procedura: " + LogStatusToString(stato) + Environment.NewLine); - log.Append("Totale spazio scansionato: " + ConvertBytesToReadableSize(spazioscansionato) + Environment.NewLine); - log.Append("Totale file scansionati: " + scansionati + Environment.NewLine); - log.Append("Errori: " + errori + Environment.NewLine); - log.Append("Warning: " + warning + Environment.NewLine); - - SetLogTextBox(log.ToString()); - } - - public void LogDispositivoFill(LogStatus stato, int creati, int salvati, long spaziototale, long spazioriempito, int errori, int warning) - { - StringBuilder log = new StringBuilder(); - - log.Append("Stato procedura: " + LogStatusToString(stato) + Environment.NewLine); - log.Append("Spazio totale da riempire: " + ConvertBytesToReadableSize(spaziototale) + Environment.NewLine); - log.Append("Spazio occupato: " + ConvertBytesToReadableSize(spazioriempito) + Environment.NewLine); - log.Append("Totale file generati: " + creati + Environment.NewLine); - log.Append("Files salvati: " + salvati + Environment.NewLine); - log.Append("Errori: " + errori + Environment.NewLine); - log.Append("Warning: " + warning + Environment.NewLine); - - SetLogTextBox(log.ToString()); - } - - public void LogDispositivoCheck(LogStatus stato, int totale, int elaborati, int inseriti, int presenti, int errori, int warning) - { - StringBuilder log = new StringBuilder(); - - log.Append("Stato procedura: " + LogStatusToString(stato) + Environment.NewLine); - log.Append("Totale da scansionare: " + totale + Environment.NewLine); - log.Append("Files scansionati: " + elaborati + Environment.NewLine); - log.Append("Files aggiornati: " + presenti + Environment.NewLine); - log.Append("Files inseriti: " + inseriti + Environment.NewLine); - log.Append("Errori: " + errori + Environment.NewLine); - log.Append("Warning: " + warning + Environment.NewLine); - - SetLogTextBox(log.ToString()); - } - - public string LogStatusToString(LogStatus status) - { - switch (status) - { - case LogStatus.ATTESA: - return "In attesa di avvio"; - case LogStatus.PREPARAZIONE: - return "Preparazione per l'elaborazione..."; - case LogStatus.ELABORAZIONE: - return "In elaborazione..."; - case LogStatus.FERMATA: - return "Stoppata dall'utente"; - case LogStatus.COMPLETATO: - return "Completato"; - case LogStatus.ERRORE: - return "Errore"; - default: - return "In attesa di avvio"; - } - } - - public void SetLogTextBox(string log) - { - if (logTextBox.InvokeRequired) - { - logTextBox.Invoke(new Action(() => logTextBox.Text = log + Environment.NewLine)); - } - else - { - logTextBox.Text = log + Environment.NewLine; - } - } - - public static string ConvertBytesToReadableSize(long bytes) - { - string[] sizes = { "B", "KB", "MB", "GB", "TB" }; - double len = bytes; - int order = 0; - - while (len >= 1024 && order < sizes.Length - 1) - { - order++; - len = len / 1024; - } - - return $"{len:0.##} {sizes[order]}"; - } - } -} diff --git a/BSHash/BSHash/Main.Designer.cs b/BSHash/BSHash/Main.Designer.cs deleted file mode 100644 index 95a9d0a..0000000 --- a/BSHash/BSHash/Main.Designer.cs +++ /dev/null @@ -1,507 +0,0 @@ -using System.Windows.Forms; - -namespace BSHash -{ - partial class Main - { - private System.ComponentModel.IContainer components = null; - - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - - base.Dispose(disposing); - } - - private System.Windows.Forms.DataGridView dataGridViewLogRows; - private System.Windows.Forms.Label labelImpostazioniPassword; - private System.Windows.Forms.Label labelImpostazioniUser; - private System.Windows.Forms.TextBox textBoxImpostazioniPassword; - private System.Windows.Forms.TextBox textBoxImpostazioniUser; - private System.Windows.Forms.Label labelImpostazioniServer; - private System.Windows.Forms.TextBox textBoxImpostazioniServer; - private ToolTip toolTipCheck; - private System.Windows.Forms.Button buttonDispositivoSfoglia; - private System.Windows.Forms.Label labelDispositivoPath; - private System.Windows.Forms.TextBox textBoxDispositivoPath; - private System.Windows.Forms.ProgressBar progressBarDispositivo; - private System.Windows.Forms.Button buttonDispositivoStop; - private System.Windows.Forms.TextBox textBoxDispositivoLog; - private System.Windows.Forms.TextBox textBoxImpostazioniDatabase; - private System.Windows.Forms.Label labelImpostazioniDatabase; - private System.Windows.Forms.Button buttonImpostazioniSalva; - private System.Windows.Forms.Button buttonExecuteStop; - private System.Windows.Forms.Label labelImpostazioniPath; - private System.Windows.Forms.TextBox textBoxImpostazioniPath; - private System.Windows.Forms.Button buttonImpostazioniBrowse; - private System.Windows.Forms.Label labelLogQuery; - private System.Windows.Forms.TextBox textBoxLogQuery; - private System.Windows.Forms.Button buttonLogQuery; - private System.Windows.Forms.Label labelLogRecordNumber; - private System.Windows.Forms.Label labelLogRecord; - private System.Windows.Forms.Button buttonDispositivoStart; - private System.Windows.Forms.RadioButton radioButtonDispositivoClear; - private System.Windows.Forms.RadioButton radioButtonDispositivoCheck; - private System.Windows.Forms.RadioButton radioButtonDispositivoFill; - private System.Windows.Forms.GroupBox groupBoxDispositivoChoice; - - private void InitializeComponent() - { - this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Main)); - this.tabHash = new System.Windows.Forms.TabControl(); - this.tabPageExecute = new System.Windows.Forms.TabPage(); - this.buttonExecuteStop = new System.Windows.Forms.Button(); - this.buttonExecuteStart = new System.Windows.Forms.Button(); - this.textBoxExecuteLog = new System.Windows.Forms.TextBox(); - this.tabPageDispositivo = new System.Windows.Forms.TabPage(); - this.groupBoxDispositivoChoice = new System.Windows.Forms.GroupBox(); - this.radioButtonDispositivoClear = new System.Windows.Forms.RadioButton(); - this.radioButtonDispositivoCheck = new System.Windows.Forms.RadioButton(); - this.radioButtonDispositivoFill = new System.Windows.Forms.RadioButton(); - this.buttonDispositivoStart = new System.Windows.Forms.Button(); - this.textBoxDispositivoLog = new System.Windows.Forms.TextBox(); - this.progressBarDispositivo = new System.Windows.Forms.ProgressBar(); - this.buttonDispositivoStop = new System.Windows.Forms.Button(); - this.buttonDispositivoSfoglia = new System.Windows.Forms.Button(); - this.labelDispositivoPath = new System.Windows.Forms.Label(); - this.textBoxDispositivoPath = new System.Windows.Forms.TextBox(); - this.tabPageLog = new System.Windows.Forms.TabPage(); - this.labelLogRecordNumber = new System.Windows.Forms.Label(); - this.labelLogRecord = new System.Windows.Forms.Label(); - this.labelLogQuery = new System.Windows.Forms.Label(); - this.textBoxLogQuery = new System.Windows.Forms.TextBox(); - this.buttonLogQuery = new System.Windows.Forms.Button(); - this.dataGridViewLogRows = new System.Windows.Forms.DataGridView(); - this.tabPageImpostazioni = new System.Windows.Forms.TabPage(); - this.buttonImpostazioniBrowse = new System.Windows.Forms.Button(); - this.labelImpostazioniPath = new System.Windows.Forms.Label(); - this.textBoxImpostazioniPath = new System.Windows.Forms.TextBox(); - this.buttonImpostazioniSalva = new System.Windows.Forms.Button(); - this.textBoxImpostazioniDatabase = new System.Windows.Forms.TextBox(); - this.labelImpostazioniDatabase = new System.Windows.Forms.Label(); - this.labelImpostazioniPassword = new System.Windows.Forms.Label(); - this.labelImpostazioniUser = new System.Windows.Forms.Label(); - this.textBoxImpostazioniPassword = new System.Windows.Forms.TextBox(); - this.textBoxImpostazioniUser = new System.Windows.Forms.TextBox(); - this.labelImpostazioniServer = new System.Windows.Forms.Label(); - this.textBoxImpostazioniServer = new System.Windows.Forms.TextBox(); - this.toolTipCheck = new System.Windows.Forms.ToolTip(this.components); - this.tabHash.SuspendLayout(); - this.tabPageExecute.SuspendLayout(); - this.tabPageDispositivo.SuspendLayout(); - this.groupBoxDispositivoChoice.SuspendLayout(); - this.tabPageLog.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.dataGridViewLogRows)).BeginInit(); - this.tabPageImpostazioni.SuspendLayout(); - this.SuspendLayout(); - // - // tabHash - // - this.tabHash.Alignment = System.Windows.Forms.TabAlignment.Left; - this.tabHash.Controls.Add(this.tabPageExecute); - this.tabHash.Controls.Add(this.tabPageDispositivo); - this.tabHash.Controls.Add(this.tabPageLog); - this.tabHash.Controls.Add(this.tabPageImpostazioni); - this.tabHash.Location = new System.Drawing.Point(12, 12); - this.tabHash.Multiline = true; - this.tabHash.Name = "tabHash"; - this.tabHash.SelectedIndex = 0; - this.tabHash.Size = new System.Drawing.Size(675, 300); - this.tabHash.TabIndex = 0; - // - // tabPageExecute - // - this.tabPageExecute.Controls.Add(this.buttonExecuteStop); - this.tabPageExecute.Controls.Add(this.buttonExecuteStart); - this.tabPageExecute.Controls.Add(this.textBoxExecuteLog); - this.tabPageExecute.Location = new System.Drawing.Point(23, 4); - this.tabPageExecute.Name = "tabPageExecute"; - this.tabPageExecute.Padding = new System.Windows.Forms.Padding(3); - this.tabPageExecute.Size = new System.Drawing.Size(648, 292); - this.tabPageExecute.TabIndex = 0; - this.tabPageExecute.Text = "Esecuzione"; - this.tabPageExecute.UseVisualStyleBackColor = true; - // - // buttonExecuteStop - // - this.buttonExecuteStop.Enabled = false; - this.buttonExecuteStop.Location = new System.Drawing.Point(313, 6); - this.buttonExecuteStop.Name = "buttonExecuteStop"; - this.buttonExecuteStop.Size = new System.Drawing.Size(327, 23); - this.buttonExecuteStop.TabIndex = 8; - this.buttonExecuteStop.Text = "Stop"; - // - // buttonExecuteStart - // - this.buttonExecuteStart.Location = new System.Drawing.Point(9, 6); - this.buttonExecuteStart.Name = "buttonExecuteStart"; - this.buttonExecuteStart.Size = new System.Drawing.Size(298, 23); - this.buttonExecuteStart.TabIndex = 4; - this.buttonExecuteStart.Text = "Avvia"; - this.buttonExecuteStart.Click += new System.EventHandler(this.StartButton_Click); - // - // textBoxExecuteLog - // - this.textBoxExecuteLog.BackColor = System.Drawing.SystemColors.MenuText; - this.textBoxExecuteLog.ForeColor = System.Drawing.SystemColors.Menu; - this.textBoxExecuteLog.Location = new System.Drawing.Point(9, 35); - this.textBoxExecuteLog.Multiline = true; - this.textBoxExecuteLog.Name = "textBoxExecuteLog"; - this.textBoxExecuteLog.ScrollBars = System.Windows.Forms.ScrollBars.Horizontal; - this.textBoxExecuteLog.Size = new System.Drawing.Size(631, 251); - this.textBoxExecuteLog.TabIndex = 7; - // - // tabPageDispositivo - // - this.tabPageDispositivo.Controls.Add(this.groupBoxDispositivoChoice); - this.tabPageDispositivo.Controls.Add(this.buttonDispositivoStart); - this.tabPageDispositivo.Controls.Add(this.textBoxDispositivoLog); - this.tabPageDispositivo.Controls.Add(this.progressBarDispositivo); - this.tabPageDispositivo.Controls.Add(this.buttonDispositivoStop); - this.tabPageDispositivo.Controls.Add(this.buttonDispositivoSfoglia); - this.tabPageDispositivo.Controls.Add(this.labelDispositivoPath); - this.tabPageDispositivo.Controls.Add(this.textBoxDispositivoPath); - this.tabPageDispositivo.Location = new System.Drawing.Point(23, 4); - this.tabPageDispositivo.Name = "tabPageDispositivo"; - this.tabPageDispositivo.Padding = new System.Windows.Forms.Padding(3); - this.tabPageDispositivo.Size = new System.Drawing.Size(648, 292); - this.tabPageDispositivo.TabIndex = 1; - this.tabPageDispositivo.Text = "Dispositivo"; - this.tabPageDispositivo.UseVisualStyleBackColor = true; - // - // groupBoxDispositivoChoice - // - this.groupBoxDispositivoChoice.Controls.Add(this.radioButtonDispositivoClear); - this.groupBoxDispositivoChoice.Controls.Add(this.radioButtonDispositivoCheck); - this.groupBoxDispositivoChoice.Controls.Add(this.radioButtonDispositivoFill); - this.groupBoxDispositivoChoice.Location = new System.Drawing.Point(9, 32); - this.groupBoxDispositivoChoice.Name = "groupBoxDispositivoChoice"; - this.groupBoxDispositivoChoice.Size = new System.Drawing.Size(160, 82); - this.groupBoxDispositivoChoice.TabIndex = 14; - this.groupBoxDispositivoChoice.TabStop = false; - this.groupBoxDispositivoChoice.Text = "Funzionalità"; - // - // radioButtonDispositivoClear - // - this.radioButtonDispositivoClear.AutoSize = true; - this.radioButtonDispositivoClear.Location = new System.Drawing.Point(6, 59); - this.radioButtonDispositivoClear.Name = "radioButtonDispositivoClear"; - this.radioButtonDispositivoClear.Size = new System.Drawing.Size(55, 17); - this.radioButtonDispositivoClear.TabIndex = 12; - this.radioButtonDispositivoClear.Text = "Pulisci"; - this.radioButtonDispositivoClear.UseVisualStyleBackColor = true; - // - // radioButtonDispositivoCheck - // - this.radioButtonDispositivoCheck.AutoSize = true; - this.radioButtonDispositivoCheck.Checked = true; - this.radioButtonDispositivoCheck.Location = new System.Drawing.Point(6, 39); - this.radioButtonDispositivoCheck.Name = "radioButtonDispositivoCheck"; - this.radioButtonDispositivoCheck.Size = new System.Drawing.Size(66, 17); - this.radioButtonDispositivoCheck.TabIndex = 11; - this.radioButtonDispositivoCheck.TabStop = true; - this.radioButtonDispositivoCheck.Text = "Controlla"; - this.toolTipCheck.SetToolTip(this.radioButtonDispositivoCheck, resources.GetString("radioButtonDispositivoCheck.ToolTip")); - this.radioButtonDispositivoCheck.UseVisualStyleBackColor = true; - // - // radioButtonDispositivoFill - // - this.radioButtonDispositivoFill.AutoSize = true; - this.radioButtonDispositivoFill.Location = new System.Drawing.Point(6, 19); - this.radioButtonDispositivoFill.Name = "radioButtonDispositivoFill"; - this.radioButtonDispositivoFill.Size = new System.Drawing.Size(57, 17); - this.radioButtonDispositivoFill.TabIndex = 10; - this.radioButtonDispositivoFill.Text = "Riempi"; - this.radioButtonDispositivoFill.UseVisualStyleBackColor = true; - // - // buttonDispositivoStart - // - this.buttonDispositivoStart.Location = new System.Drawing.Point(175, 33); - this.buttonDispositivoStart.Name = "buttonDispositivoStart"; - this.buttonDispositivoStart.Size = new System.Drawing.Size(467, 23); - this.buttonDispositivoStart.TabIndex = 13; - this.buttonDispositivoStart.Text = "Avvia"; - this.buttonDispositivoStart.UseVisualStyleBackColor = true; - this.buttonDispositivoStart.Click += new System.EventHandler(this.buttonDispositivoStart_ClickAsync); - // - // textBoxDispositivoLog - // - this.textBoxDispositivoLog.BackColor = System.Drawing.SystemColors.MenuText; - this.textBoxDispositivoLog.ForeColor = System.Drawing.SystemColors.Menu; - this.textBoxDispositivoLog.Location = new System.Drawing.Point(9, 120); - this.textBoxDispositivoLog.Multiline = true; - this.textBoxDispositivoLog.Name = "textBoxDispositivoLog"; - this.textBoxDispositivoLog.ScrollBars = System.Windows.Forms.ScrollBars.Horizontal; - this.textBoxDispositivoLog.Size = new System.Drawing.Size(633, 166); - this.textBoxDispositivoLog.TabIndex = 8; - // - // progressBarDispositivo - // - this.progressBarDispositivo.Location = new System.Drawing.Point(175, 91); - this.progressBarDispositivo.Name = "progressBarDispositivo"; - this.progressBarDispositivo.Size = new System.Drawing.Size(467, 23); - this.progressBarDispositivo.TabIndex = 6; - // - // buttonDispositivoStop - // - this.buttonDispositivoStop.Enabled = false; - this.buttonDispositivoStop.Location = new System.Drawing.Point(175, 62); - this.buttonDispositivoStop.Name = "buttonDispositivoStop"; - this.buttonDispositivoStop.Size = new System.Drawing.Size(467, 23); - this.buttonDispositivoStop.TabIndex = 5; - this.buttonDispositivoStop.Text = "Stop"; - this.buttonDispositivoStop.UseVisualStyleBackColor = true; - this.buttonDispositivoStop.Click += new System.EventHandler(this.buttonDispositivoStop_Click); - // - // buttonDispositivoSfoglia - // - this.buttonDispositivoSfoglia.Location = new System.Drawing.Point(567, 4); - this.buttonDispositivoSfoglia.Name = "buttonDispositivoSfoglia"; - this.buttonDispositivoSfoglia.Size = new System.Drawing.Size(75, 23); - this.buttonDispositivoSfoglia.TabIndex = 2; - this.buttonDispositivoSfoglia.Text = "Sfoglia"; - this.buttonDispositivoSfoglia.UseVisualStyleBackColor = true; - this.buttonDispositivoSfoglia.Click += new System.EventHandler(this.buttonDispositivoSfoglia_Click); - // - // labelDispositivoPath - // - this.labelDispositivoPath.AutoSize = true; - this.labelDispositivoPath.Location = new System.Drawing.Point(6, 9); - this.labelDispositivoPath.Name = "labelDispositivoPath"; - this.labelDispositivoPath.Size = new System.Drawing.Size(49, 13); - this.labelDispositivoPath.TabIndex = 1; - this.labelDispositivoPath.Text = "Percorso"; - // - // textBoxDispositivoPath - // - this.textBoxDispositivoPath.Location = new System.Drawing.Point(61, 6); - this.textBoxDispositivoPath.Name = "textBoxDispositivoPath"; - this.textBoxDispositivoPath.ReadOnly = true; - this.textBoxDispositivoPath.Size = new System.Drawing.Size(500, 20); - this.textBoxDispositivoPath.TabIndex = 0; - // - // tabPageLog - // - this.tabPageLog.Controls.Add(this.labelLogRecordNumber); - this.tabPageLog.Controls.Add(this.labelLogRecord); - this.tabPageLog.Controls.Add(this.labelLogQuery); - this.tabPageLog.Controls.Add(this.textBoxLogQuery); - this.tabPageLog.Controls.Add(this.buttonLogQuery); - this.tabPageLog.Controls.Add(this.dataGridViewLogRows); - this.tabPageLog.ImeMode = System.Windows.Forms.ImeMode.NoControl; - this.tabPageLog.Location = new System.Drawing.Point(23, 4); - this.tabPageLog.Name = "tabPageLog"; - this.tabPageLog.Padding = new System.Windows.Forms.Padding(3); - this.tabPageLog.Size = new System.Drawing.Size(648, 292); - this.tabPageLog.TabIndex = 1; - this.tabPageLog.Text = "Log"; - this.tabPageLog.UseVisualStyleBackColor = true; - // - // labelLogRecordNumber - // - this.labelLogRecordNumber.AutoSize = true; - this.labelLogRecordNumber.Location = new System.Drawing.Point(88, 276); - this.labelLogRecordNumber.Name = "labelLogRecordNumber"; - this.labelLogRecordNumber.Size = new System.Drawing.Size(13, 13); - this.labelLogRecordNumber.TabIndex = 9; - this.labelLogRecordNumber.Text = "0"; - // - // labelLogRecord - // - this.labelLogRecord.AutoSize = true; - this.labelLogRecord.Location = new System.Drawing.Point(6, 276); - this.labelLogRecord.Name = "labelLogRecord"; - this.labelLogRecord.Size = new System.Drawing.Size(76, 13); - this.labelLogRecord.TabIndex = 8; - this.labelLogRecord.Text = "Record estratti"; - // - // labelLogQuery - // - this.labelLogQuery.AutoSize = true; - this.labelLogQuery.Location = new System.Drawing.Point(6, 13); - this.labelLogQuery.Name = "labelLogQuery"; - this.labelLogQuery.Size = new System.Drawing.Size(35, 13); - this.labelLogQuery.TabIndex = 7; - this.labelLogQuery.Text = "Query"; - // - // textBoxLogQuery - // - this.textBoxLogQuery.Enabled = false; - this.textBoxLogQuery.Location = new System.Drawing.Point(47, 10); - this.textBoxLogQuery.Name = "textBoxLogQuery"; - this.textBoxLogQuery.ReadOnly = true; - this.textBoxLogQuery.Size = new System.Drawing.Size(500, 20); - this.textBoxLogQuery.TabIndex = 6; - this.textBoxLogQuery.Text = "SELECT Date, Type, Message FROM Log ORDER BY Date DESC"; - // - // buttonLogQuery - // - this.buttonLogQuery.Location = new System.Drawing.Point(553, 8); - this.buttonLogQuery.Name = "buttonLogQuery"; - this.buttonLogQuery.Size = new System.Drawing.Size(89, 23); - this.buttonLogQuery.TabIndex = 5; - this.buttonLogQuery.Text = "Esegui"; - this.buttonLogQuery.UseVisualStyleBackColor = true; - this.buttonLogQuery.Click += new System.EventHandler(this.buttonLogQuery_Click); - // - // dataGridViewLogRows - // - this.dataGridViewLogRows.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill; - this.dataGridViewLogRows.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; - this.dataGridViewLogRows.Location = new System.Drawing.Point(6, 37); - this.dataGridViewLogRows.Name = "dataGridViewLogRows"; - this.dataGridViewLogRows.ReadOnly = true; - this.dataGridViewLogRows.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; - this.dataGridViewLogRows.Size = new System.Drawing.Size(636, 236); - this.dataGridViewLogRows.TabIndex = 0; - // - // tabPageImpostazioni - // - this.tabPageImpostazioni.Controls.Add(this.buttonImpostazioniBrowse); - this.tabPageImpostazioni.Controls.Add(this.labelImpostazioniPath); - this.tabPageImpostazioni.Controls.Add(this.textBoxImpostazioniPath); - this.tabPageImpostazioni.Controls.Add(this.buttonImpostazioniSalva); - this.tabPageImpostazioni.Controls.Add(this.textBoxImpostazioniDatabase); - this.tabPageImpostazioni.Controls.Add(this.labelImpostazioniDatabase); - this.tabPageImpostazioni.Controls.Add(this.labelImpostazioniPassword); - this.tabPageImpostazioni.Controls.Add(this.labelImpostazioniUser); - this.tabPageImpostazioni.Controls.Add(this.textBoxImpostazioniPassword); - this.tabPageImpostazioni.Controls.Add(this.textBoxImpostazioniUser); - this.tabPageImpostazioni.Controls.Add(this.labelImpostazioniServer); - this.tabPageImpostazioni.Controls.Add(this.textBoxImpostazioniServer); - this.tabPageImpostazioni.Location = new System.Drawing.Point(23, 4); - this.tabPageImpostazioni.Name = "tabPageImpostazioni"; - this.tabPageImpostazioni.Padding = new System.Windows.Forms.Padding(3); - this.tabPageImpostazioni.Size = new System.Drawing.Size(648, 292); - this.tabPageImpostazioni.TabIndex = 1; - this.tabPageImpostazioni.Text = "Impostazioni"; - this.tabPageImpostazioni.UseVisualStyleBackColor = true; - // - // buttonImpostazioniBrowse - // - this.buttonImpostazioniBrowse.Location = new System.Drawing.Point(567, 109); - this.buttonImpostazioniBrowse.Name = "buttonImpostazioniBrowse"; - this.buttonImpostazioniBrowse.Size = new System.Drawing.Size(75, 23); - this.buttonImpostazioniBrowse.TabIndex = 11; - this.buttonImpostazioniBrowse.Text = "Sfoglia"; - this.buttonImpostazioniBrowse.UseVisualStyleBackColor = true; - this.buttonImpostazioniBrowse.Click += new System.EventHandler(this.buttonImpostazioniBrowse_Click); - // - // labelImpostazioniPath - // - this.labelImpostazioniPath.AutoSize = true; - this.labelImpostazioniPath.Location = new System.Drawing.Point(6, 114); - this.labelImpostazioniPath.Name = "labelImpostazioniPath"; - this.labelImpostazioniPath.Size = new System.Drawing.Size(49, 13); - this.labelImpostazioniPath.TabIndex = 10; - this.labelImpostazioniPath.Text = "Percorso"; - // - // textBoxImpostazioniPath - // - this.textBoxImpostazioniPath.Location = new System.Drawing.Point(70, 111); - this.textBoxImpostazioniPath.Name = "textBoxImpostazioniPath"; - this.textBoxImpostazioniPath.Size = new System.Drawing.Size(491, 20); - this.textBoxImpostazioniPath.TabIndex = 9; - // - // buttonImpostazioniSalva - // - this.buttonImpostazioniSalva.Location = new System.Drawing.Point(567, 137); - this.buttonImpostazioniSalva.Name = "buttonImpostazioniSalva"; - this.buttonImpostazioniSalva.Size = new System.Drawing.Size(75, 23); - this.buttonImpostazioniSalva.TabIndex = 8; - this.buttonImpostazioniSalva.Text = "Salva"; - this.buttonImpostazioniSalva.UseVisualStyleBackColor = true; - this.buttonImpostazioniSalva.Click += new System.EventHandler(this.buttonImpostazioniSalva_Click); - // - // textBoxImpostazioniDatabase - // - this.textBoxImpostazioniDatabase.Location = new System.Drawing.Point(70, 85); - this.textBoxImpostazioniDatabase.Name = "textBoxImpostazioniDatabase"; - this.textBoxImpostazioniDatabase.Size = new System.Drawing.Size(572, 20); - this.textBoxImpostazioniDatabase.TabIndex = 7; - // - // labelImpostazioniDatabase - // - this.labelImpostazioniDatabase.AutoSize = true; - this.labelImpostazioniDatabase.Location = new System.Drawing.Point(6, 88); - this.labelImpostazioniDatabase.Name = "labelImpostazioniDatabase"; - this.labelImpostazioniDatabase.Size = new System.Drawing.Size(53, 13); - this.labelImpostazioniDatabase.TabIndex = 6; - this.labelImpostazioniDatabase.Text = "Database"; - // - // labelImpostazioniPassword - // - this.labelImpostazioniPassword.AutoSize = true; - this.labelImpostazioniPassword.Location = new System.Drawing.Point(6, 62); - this.labelImpostazioniPassword.Name = "labelImpostazioniPassword"; - this.labelImpostazioniPassword.Size = new System.Drawing.Size(53, 13); - this.labelImpostazioniPassword.TabIndex = 5; - this.labelImpostazioniPassword.Text = "Password"; - // - // labelImpostazioniUser - // - this.labelImpostazioniUser.AutoSize = true; - this.labelImpostazioniUser.Location = new System.Drawing.Point(6, 36); - this.labelImpostazioniUser.Name = "labelImpostazioniUser"; - this.labelImpostazioniUser.Size = new System.Drawing.Size(39, 13); - this.labelImpostazioniUser.TabIndex = 4; - this.labelImpostazioniUser.Text = "Utente"; - // - // textBoxImpostazioniPassword - // - this.textBoxImpostazioniPassword.Location = new System.Drawing.Point(70, 59); - this.textBoxImpostazioniPassword.Name = "textBoxImpostazioniPassword"; - this.textBoxImpostazioniPassword.Size = new System.Drawing.Size(572, 20); - this.textBoxImpostazioniPassword.TabIndex = 3; - // - // textBoxImpostazioniUser - // - this.textBoxImpostazioniUser.Location = new System.Drawing.Point(70, 33); - this.textBoxImpostazioniUser.Name = "textBoxImpostazioniUser"; - this.textBoxImpostazioniUser.Size = new System.Drawing.Size(572, 20); - this.textBoxImpostazioniUser.TabIndex = 2; - // - // labelImpostazioniServer - // - this.labelImpostazioniServer.AutoSize = true; - this.labelImpostazioniServer.Location = new System.Drawing.Point(6, 10); - this.labelImpostazioniServer.Name = "labelImpostazioniServer"; - this.labelImpostazioniServer.Size = new System.Drawing.Size(38, 13); - this.labelImpostazioniServer.TabIndex = 1; - this.labelImpostazioniServer.Text = "Server"; - // - // textBoxImpostazioniServer - // - this.textBoxImpostazioniServer.Location = new System.Drawing.Point(70, 7); - this.textBoxImpostazioniServer.Name = "textBoxImpostazioniServer"; - this.textBoxImpostazioniServer.Size = new System.Drawing.Size(572, 20); - this.textBoxImpostazioniServer.TabIndex = 0; - // - // Main - // - this.ClientSize = new System.Drawing.Size(698, 323); - this.Controls.Add(this.tabHash); - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MaximizeBox = false; - this.Name = "Main"; - this.Text = "BS Hash Management"; - this.tabHash.ResumeLayout(false); - this.tabPageExecute.ResumeLayout(false); - this.tabPageExecute.PerformLayout(); - this.tabPageDispositivo.ResumeLayout(false); - this.tabPageDispositivo.PerformLayout(); - this.groupBoxDispositivoChoice.ResumeLayout(false); - this.groupBoxDispositivoChoice.PerformLayout(); - this.tabPageLog.ResumeLayout(false); - this.tabPageLog.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.dataGridViewLogRows)).EndInit(); - this.tabPageImpostazioni.ResumeLayout(false); - this.tabPageImpostazioni.PerformLayout(); - this.ResumeLayout(false); - } - } -} diff --git a/BSHash/BSHash/Main.cs b/BSHash/BSHash/Main.cs deleted file mode 100644 index 795a298..0000000 --- a/BSHash/BSHash/Main.cs +++ /dev/null @@ -1,330 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Data.SqlClient; -using System.Drawing; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Security.Policy; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Forms; - -namespace BSHash -{ - public partial class Main : Form - { - //Grafica - public Button buttonExecuteStart; - public TextBox textBoxExecuteLog; - public Database databaseHelper; - public Calculator fileHashCalculator; - public Storage storage; - public TabControl tabHash; - public TabPage tabPageExecute; - public TabPage tabPageLog; - public TabPage tabPageDispositivo; - public TabPage tabPageImpostazioni; - public Logger logger; - public Logger loggerDispositivo; - - //cancellazione - private CancellationTokenSource _cancellationTokenSource; - // Nella classe Main.cs - - - public Main() - { - InitializeComponent(); - LoadSettings(); - - textBoxDispositivoPath.Text = Properties.Settings.Default.Path; - - databaseHelper = new Database(); - logger = new Logger(textBoxExecuteLog, databaseHelper); - loggerDispositivo = new Logger(textBoxDispositivoLog, databaseHelper); - fileHashCalculator = new Calculator(logger); - storage = new Storage(loggerDispositivo); - tabHash.SelectedIndexChanged += new EventHandler(tabControl_SelectedIndexChanged); - } - - private async void StartButton_Click(object sender, EventArgs e) - { - // Inizializza il CancellationTokenSource - _cancellationTokenSource = new CancellationTokenSource(); - CancellationToken cancellationToken = _cancellationTokenSource.Token; - - // Disabilita i controlli durante l'esecuzione - buttonExecuteStart.Enabled = false; - buttonExecuteStop.Enabled = true; - - long spazioscansionato = 0; - long scansionati = 0; - int errori = 0; - int warning = 0; - - logger.LogEsecuzioneExecute(LogStatus.PREPARAZIONE, spazioscansionato, scansionati, errori, warning); - logger.Log("Inizio procedura principale.", LogType.INFO); - - // Esegui il calcolo degli hash e l'inserimento nel database in un thread separato - await Task.Run(async () => - { - while (!cancellationToken.IsCancellationRequested) - { - logger.Log("Scansione database... ", LogType.INFO); - - DataTable hashes = databaseHelper.GetHashes(); - - int totalFiles = hashes.Rows.Count; - int processedFiles = 0; - - logger.Log("Trovati " + totalFiles.ToString() + " da scansionare.", LogType.INFO); - - foreach (DataRow row in hashes.Rows) - { - if (cancellationToken.IsCancellationRequested) - { - logger.Log("Procedura interrotta dall'utente.", LogType.WARN); - break; - } - - string filePath = row["Path"].ToString(); - string hash = row["Hash"].ToString(); - - processedFiles++; - scansionati++; - - logger.Log("Scansione file " + processedFiles.ToString() + " / " + totalFiles.ToString() + ". Percorso: " + filePath, LogType.INFO); - - if (!File.Exists(filePath)) - { - logger.Log("Il file " + filePath + " non esiste.", LogType.ERROR); - continue; - } - - FileInfo fileInfo = new FileInfo(filePath); - spazioscansionato += fileInfo.Length; - - logger.Log("Calcolo hash per il file " + filePath + ".", LogType.INFO); - - string calculatedHash = fileHashCalculator.CalculateHash(filePath); - - if (calculatedHash == null) - { - logger.Log("Non è stato possibile calcolare l'hash del file " + filePath, LogType.ERROR); - continue; - } - - if (calculatedHash != hash) - { - logger.Log("L'hash calcolato dal file (" + calculatedHash + ") è diverso da quell inserito nel database (" + hash + ")", LogType.ERROR); - continue; - } - - Network network = new Network(logger); - - var sendDataHashTask = network.SendDataHash(calculatedHash); - if (await sendDataHashTask != Network.OK) - { - logger.Log("Errore nell'invio dell'hash " + calculatedHash, LogType.INFO); - continue; - } - - var getDataHashTask = network.GetDataHash(calculatedHash); - if (await getDataHashTask != Network.OK) - { - logger.Log("Errore nella ricezione della risposta dell'hash " + calculatedHash, LogType.INFO); - continue; - } - - databaseHelper.InsertHistory(calculatedHash); - logger.LogEsecuzioneExecute(LogStatus.ELABORAZIONE, spazioscansionato, scansionati, errori, warning); - } - - logger.Log("Calcolati correttamente " + processedFiles.ToString() + " su " + totalFiles.ToString() + ".", LogType.INFO); - } - }, cancellationToken); - - logger.LogEsecuzioneExecute(LogStatus.FERMATA, spazioscansionato, scansionati, errori, warning); - logger.Log("Procedura terminata.", LogType.INFO); - - // Riabilita i controlli dopo l'esecuzione - buttonExecuteStart.Enabled = true; - buttonExecuteStop.Enabled = false; - } - - private void tabControl_SelectedIndexChanged(object sender, EventArgs e) - { - if (tabHash.SelectedTab == tabPageLog) - { - //LoadLogs(); - } - } - - private void LoadLogs() - { - DataTable logs = databaseHelper.GetLogs(textBoxLogQuery.Text); - dataGridViewLogRows.DataSource = logs; - labelLogRecordNumber.Text = dataGridViewLogRows.RowCount.ToString(); - } - - private void buttonDispositivoSfoglia_Click(object sender, EventArgs e) - { - using (FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog()) - { - if (folderBrowserDialog.ShowDialog() == DialogResult.OK) - { - textBoxDispositivoPath.Text = folderBrowserDialog.SelectedPath; - } - } - } - - private void LoadSettings() - { - textBoxImpostazioniServer.Text = Properties.Settings.Default.Server; - textBoxImpostazioniUser.Text = Properties.Settings.Default.User; - textBoxImpostazioniPassword.Text = Properties.Settings.Default.Password; - textBoxImpostazioniDatabase.Text = Properties.Settings.Default.Database; - textBoxImpostazioniPath.Text = Properties.Settings.Default.Path; - } - - private void SaveSettings() - { - Properties.Settings.Default.Server = textBoxImpostazioniServer.Text; - Properties.Settings.Default.User = textBoxImpostazioniUser.Text; - Properties.Settings.Default.Password = textBoxImpostazioniPassword.Text; - Properties.Settings.Default.Database = textBoxImpostazioniDatabase.Text; - Properties.Settings.Default.Path = textBoxImpostazioniPath.Text; - Properties.Settings.Default.Save(); - } - - protected override void OnFormClosing(FormClosingEventArgs e) - { - SaveSettings(); - base.OnFormClosing(e); - } - - private void buttonImpostazioniSalva_Click(object sender, EventArgs e) - { - SaveSettings(); - } - - private void SetControlEnabled(bool enabled) - { - if (InvokeRequired) - { - Invoke(new Action(SetControlEnabled), enabled); - } - else - { - buttonDispositivoStart.Enabled = enabled; - buttonDispositivoStop.Enabled = !enabled; - } - } - - private void buttonImpostazioniBrowse_Click(object sender, EventArgs e) - { - using (FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog()) - { - if (folderBrowserDialog.ShowDialog() == DialogResult.OK) - { - textBoxImpostazioniPath.Text = folderBrowserDialog.SelectedPath; - } - } - } - - private void buttonLogQuery_Click(object sender, EventArgs e) - { - LoadLogs(); - } - - private async void buttonDispositivoStart_ClickAsync(object sender, EventArgs e) - { - if (radioButtonDispositivoCheck.Checked) - { - // Controlla se il percorso esiste - if (!Directory.Exists(textBoxDispositivoPath.Text)) - { - loggerDispositivo.Log("Errore: Il percorso specificato non esiste.", LogType.FATAL); - return; - } - - loggerDispositivo.Log("Caricamento informazioni per esecuzione...", LogType.INFO); - - // Disabilita i controlli prima dell'esecuzione e abilita il pulsante Stop - SetControlEnabled(false); - buttonDispositivoStop.Enabled = true; - - // Esegui il riempimento del percorso in un thread separato - await Task.Run(() => - { - // Avvio il riempimento del dispositivo - storage.StartCheckFiles(textBoxDispositivoPath.Text, progressBarDispositivo, buttonDispositivoStart, buttonDispositivoStop); - }); - } - - if(radioButtonDispositivoFill.Checked) - { - // Controlla se il percorso esiste - if (!Directory.Exists(textBoxDispositivoPath.Text)) - { - loggerDispositivo.Log("Errore: Il percorso specificato non esiste.", LogType.FATAL); - return; - } - - loggerDispositivo.Log("Caricamento informazioni per esecuzione...", LogType.INFO); - - // Disabilita i controlli prima dell'esecuzione e abilita il pulsante Stop - SetControlEnabled(false); - buttonDispositivoStop.Enabled = true; - - // Esegui il riempimento del percorso in un thread separato - await Task.Run(() => - { - // Avvio il riempimento del dispositivo - storage.StartFillStorage(textBoxDispositivoPath.Text, progressBarDispositivo, buttonDispositivoStart, buttonDispositivoStop); - }); - } - - if (radioButtonDispositivoClear.Checked) - { - // Controlla se il percorso esiste - if (!Directory.Exists(textBoxDispositivoPath.Text)) - { - loggerDispositivo.Log("Errore: Il percorso specificato non esiste.", LogType.FATAL); - return; - } - - // Disabilita i controlli prima dell'esecuzione e abilita il pulsante Stop - SetControlEnabled(false); - buttonDispositivoStop.Enabled = true; - - // Esegui la pulizia del percorso in un thread separato - await Task.Run(() => - { - // Avvio la pulizia del dispositivo in un thread separato - storage.StartClearStorage(textBoxDispositivoPath.Text, progressBarDispositivo, buttonDispositivoStart, buttonDispositivoStop); - }); - } - } - - private void buttonDispositivoStop_Click(object sender, EventArgs e) - { - //Fermo l'attività avviata - storage.StopFillStorage(progressBarDispositivo, buttonDispositivoStart, buttonDispositivoStop); - //storage.StopCheckStorage(progressBarDispositivo, buttonDispositivoStart, buttonDispositivoStop); - storage.StopClearStorage(progressBarDispositivo, buttonDispositivoStart, buttonDispositivoStop); - - // Riabilita i controlli dopo l'esecuzione - SetControlEnabled(true); - } - private void buttonExecuteStop_Click(object sender, EventArgs e) - { - // Annulla l'operazione - _cancellationTokenSource?.Cancel(); - } - } -} diff --git a/BSHash/BSHash/Manager/ApiManager.cs b/BSHash/BSHash/Manager/ApiManager.cs new file mode 100644 index 0000000..f33ad95 --- /dev/null +++ b/BSHash/BSHash/Manager/ApiManager.cs @@ -0,0 +1,267 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using System.Text.Json; +using System.Threading; + +namespace BSHash +{ + public class ApiManager + { + private readonly HttpClient _httpClient; + private readonly Database _database; + private readonly Logger _logger; + private readonly string _apiEndpoint; + private readonly string _apiKey; + private readonly int _batchSize; + private Manager.Database database; + + public ApiManager(Database database, Logger logger) + { + _database = database; + _logger = logger; + _httpClient = new HttpClient(); + + // Load settings from database + _apiEndpoint = _database.GetSetting("api_endpoint_url") ?? "https://api.hashkeeper.pro/submit"; + _apiKey = _database.GetSetting("api_key") ?? ""; + _batchSize = int.TryParse(_database.GetSetting("batch_size"), out int size) ? size : 100; + + // Configure HTTP client + _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}"); + _httpClient.DefaultRequestHeaders.Add("User-Agent", "HashKeeper-Pro/1.0"); + _httpClient.Timeout = TimeSpan.FromMinutes(5); + } + + public ApiManager(Manager.Database database) + { + this.database = database; + } + + public async Task SubmitPendingHashesAsync(CancellationToken cancellationToken = default) + { + var result = new ApiSubmissionResult + { + StartTime = DateTime.Now + }; + + try + { + // Check if API is enabled + var apiEnabled = bool.TryParse(_database.GetSetting("enable_api_sending"), out bool enabled) && enabled; + if (!apiEnabled) + { + result.Status = "Disabled"; + result.Message = "API submission is disabled in settings"; + return result; + } + + if (string.IsNullOrEmpty(_apiKey)) + { + result.Status = "Error"; + result.Message = "API key not configured"; + return result; + } + + _logger.Log("Avvio invio hash all'API esterna", LogType.INFO); + + // Get unsent hashes in batches + var unsentHashes = _database.GetUnsentHashes(_batchSize); + result.TotalHashes = unsentHashes.Rows.Count; + + if (result.TotalHashes == 0) + { + result.Status = "Completed"; + result.Message = "No hashes to send"; + _logger.Log("Nessun hash da inviare", LogType.INFO); + return result; + } + + _logger.Log($"Trovati {result.TotalHashes} hash da inviare", LogType.INFO); + + var hashBatch = new List(); + + foreach (DataRow row in unsentHashes.Rows) + { + if (cancellationToken.IsCancellationRequested) + { + result.Status = "Cancelled"; + break; + } + + var submission = new HashSubmission + { + Hash = row.Field("current_hash"), + FilePath = row.Field("file_path"), + FirstScanned = row.Field("first_scanned_date"), + LastScanned = row.Field("last_scanned_date"), + ClientId = Environment.MachineName + }; + + hashBatch.Add(submission); + } + + // Submit batch to API + var submissionSuccess = await SubmitHashBatchAsync(hashBatch); + + if (submissionSuccess) + { + // Mark hashes as sent + foreach (var submission in hashBatch) + { + _database.MarkHashAsSent(submission.Hash); + result.SuccessfulSubmissions++; + } + + result.Status = "Completed"; + result.Message = $"Successfully submitted {result.SuccessfulSubmissions} hashes"; + _logger.Log($"Inviati con successo {result.SuccessfulSubmissions} hash", LogType.INFO); + } + else + { + result.Status = "Error"; + result.Message = "Failed to submit hash batch"; + result.FailedSubmissions = hashBatch.Count; + _logger.Log("Errore durante l'invio del batch di hash", LogType.ERROR); + } + } + catch (Exception ex) + { + result.Status = "Error"; + result.Message = ex.Message; + _logger.Log($"Errore durante l'invio hash: {ex.Message}", LogType.ERROR); + } + finally + { + result.EndTime = DateTime.Now; + } + + return result; + } + + private async Task SubmitHashBatchAsync(List hashBatch) + { + try + { + var payload = new + { + hashes = hashBatch, + timestamp = DateTime.UtcNow, + client_version = "1.0.0" + }; + + var json = JsonSerializer.Serialize(payload, new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }); + + var content = new StringContent(json, Encoding.UTF8, "application/json"); + + _logger.Log($"Invio batch di {hashBatch.Count} hash a {_apiEndpoint}", LogType.DEBUG); + + var response = await _httpClient.PostAsync(_apiEndpoint, content); + + if (response.IsSuccessStatusCode) + { + var responseContent = await response.Content.ReadAsStringAsync(); + _logger.Log($"Risposta API: {response.StatusCode}", LogType.DEBUG); + return true; + } + else + { + var errorContent = await response.Content.ReadAsStringAsync(); + _logger.Log($"Errore API: {response.StatusCode} - {errorContent}", LogType.ERROR); + return false; + } + } + catch (HttpRequestException ex) + { + _logger.Log($"Errore di rete durante l'invio: {ex.Message}", LogType.ERROR); + return false; + } + catch (TaskCanceledException ex) + { + _logger.Log($"Timeout durante l'invio: {ex.Message}", LogType.ERROR); + return false; + } + catch (Exception ex) + { + _logger.Log($"Errore imprevisto durante l'invio: {ex.Message}", LogType.ERROR); + return false; + } + } + + public async Task CheckApiHealthAsync() + { + var result = new ApiHealthResult + { + CheckTime = DateTime.Now + }; + + try + { + var healthEndpoint = _apiEndpoint.Replace("/submit", "/health"); + var response = await _httpClient.GetAsync(healthEndpoint); + + result.IsHealthy = response.IsSuccessStatusCode; + result.StatusCode = (int)response.StatusCode; + result.ResponseTime = response.Headers.Date?.Subtract(DateTime.UtcNow) ?? TimeSpan.Zero; + + if (result.IsHealthy) + { + var content = await response.Content.ReadAsStringAsync(); + result.Message = "API is healthy"; + } + else + { + result.Message = $"API returned status code: {response.StatusCode}"; + } + } + catch (Exception ex) + { + result.IsHealthy = false; + result.Message = ex.Message; + } + + return result; + } + + public void Dispose() + { + _httpClient?.Dispose(); + } + } + + public class HashSubmission + { + public string Hash { get; set; } + public string FilePath { get; set; } + public DateTime FirstScanned { get; set; } + public DateTime LastScanned { get; set; } + public string ClientId { get; set; } + } + + public class ApiSubmissionResult + { + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + public int TotalHashes { get; set; } + public int SuccessfulSubmissions { get; set; } + public int FailedSubmissions { get; set; } + public string Status { get; set; } + public string Message { get; set; } + public TimeSpan Duration => EndTime - StartTime; + } + + public class ApiHealthResult + { + public DateTime CheckTime { get; set; } + public bool IsHealthy { get; set; } + public int StatusCode { get; set; } + public TimeSpan ResponseTime { get; set; } + public string Message { get; set; } + } +} \ No newline at end of file diff --git a/BSHash/BSHash/Manager/Calculator.cs b/BSHash/BSHash/Manager/Calculator.cs new file mode 100644 index 0000000..ca1752c --- /dev/null +++ b/BSHash/BSHash/Manager/Calculator.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Security.Cryptography; +using System.Windows.Forms; + +namespace BSHash +{ + public class Calculator + { + private Logger _logger; + + public Calculator(Logger logger) + { + _logger = logger; + } + + /// + /// Calcola l'hash SHA512 del file specificato. + /// + public string CalculateHashSHA512(string filePath) + { + try + { + using (SHA512 sha512 = SHA512.Create()) + { + using (FileStream fileStream = File.OpenRead(filePath)) + { + byte[] hashBytes = sha512.ComputeHash(fileStream); + string hash = BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant(); + + _logger.Log("Hash SHA512 " + hash + " calcolato per il file " + filePath.ToString(), LogType.INFO); + + return hash; + } + } + } + catch (Exception ex) + { + _logger.Log("Errore nella lettura o hash SHA512 del file " + filePath.ToString() + ".\nErrore: " + ex.Message.ToString(), LogType.ERROR); + return null; + } + } + + /// + /// [DEPRECATO] Calcola l'hash SHA256 del file specificato. + /// + [Obsolete("Usa CalculateHashSHA512 per il calcolo dell'hash.")] + public string CalculateHashSHA256(string filePath) + { + try + { + using (SHA256 sha256 = SHA256.Create()) + { + using (FileStream fileStream = File.OpenRead(filePath)) + { + byte[] hashBytes = sha256.ComputeHash(fileStream); + string hash = BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant(); + + _logger.Log("Hash SHA256 " + hash + " calcolato per il file " + filePath.ToString(), LogType.INFO); + + return hash; + } + } + } + catch (Exception ex) + { + _logger.Log("Errore nella lettura o hash SHA256 del file " + filePath.ToString() + ".\nErrore: " + ex.Message.ToString(), LogType.ERROR); + return null; + } + } + } +} diff --git a/BSHash/BSHash/Manager/CredentialManager.cs b/BSHash/BSHash/Manager/CredentialManager.cs new file mode 100644 index 0000000..59ea7aa --- /dev/null +++ b/BSHash/BSHash/Manager/CredentialManager.cs @@ -0,0 +1,70 @@ +using System; +using System.Security.Cryptography; +using System.Text; +using System.Text.Json; + +namespace BSHash +{ + public static class CredentialManager + { + public static void SaveCredentials(string username, string password) + { + try + { + var credentials = new UserCredentials { Username = username, Password = password }; + var json = JsonSerializer.Serialize(credentials); + var encrypted = ProtectData(json); + + Properties.Settings.Default.SavedCredentials = encrypted; + Properties.Settings.Default.Save(); + } + catch (Exception ex) + { + throw new Exception($"Errore nel salvataggio delle credenziali: {ex.Message}"); + } + } + + public static UserCredentials LoadCredentials() + { + try + { + var encrypted = Properties.Settings.Default.SavedCredentials; + if (string.IsNullOrEmpty(encrypted)) + return null; + + var decrypted = UnprotectData(encrypted); + return JsonSerializer.Deserialize(decrypted); + } + catch + { + return null; + } + } + + public static void ClearCredentials() + { + Properties.Settings.Default.SavedCredentials = string.Empty; + Properties.Settings.Default.Save(); + } + + private static string ProtectData(string data) + { + byte[] dataBytes = Encoding.UTF8.GetBytes(data); + byte[] protectedBytes = ProtectedData.Protect(dataBytes, null, DataProtectionScope.CurrentUser); + return Convert.ToBase64String(protectedBytes); + } + + private static string UnprotectData(string protectedData) + { + byte[] protectedBytes = Convert.FromBase64String(protectedData); + byte[] dataBytes = ProtectedData.Unprotect(protectedBytes, null, DataProtectionScope.CurrentUser); + return Encoding.UTF8.GetString(dataBytes); + } + } + + public class UserCredentials + { + public string Username { get; set; } + public string Password { get; set; } + } +} diff --git a/BSHash/BSHash/Manager/Database.cs b/BSHash/BSHash/Manager/Database.cs new file mode 100644 index 0000000..3853b1a --- /dev/null +++ b/BSHash/BSHash/Manager/Database.cs @@ -0,0 +1,689 @@ +using System; +using System.Data; +using System.Data.SqlClient; +using System.Windows.Forms; +using System.Threading.Tasks; +using System.IO; +using System.Collections.Generic; +using System.Security.Cryptography; +using System.Text; + +namespace BSHash.Manager +{ + public enum LogType + { + DEBUG = 0, + INFO = 1, + WARNING = 2, + ERROR = 3, + FATAL = 4 + } + + public class Database + { + private const string IdColumnName = "id"; + private string _connectionString; + + public Database() + { + BuildConnectionString(); + } + + private void BuildConnectionString() + { + var builder = new SqlConnectionStringBuilder + { + DataSource = Properties.Settings.Default.DatabaseServer, + InitialCatalog = Properties.Settings.Default.DatabaseName, + UserID = Properties.Settings.Default.DatabaseUser, + Password = Properties.Settings.Default.DatabasePassword, + ConnectTimeout = 60, + TrustServerCertificate = true + }; + + _connectionString = builder.ConnectionString; + } + + public async Task TestConnectionAsync(string customConnectionString = null) + { + string connectionString = customConnectionString ?? _connectionString; + try + { + using (var connection = new SqlConnection(connectionString)) + { + await connection.OpenAsync(); + using (var command = new SqlCommand("SELECT 1", connection)) + { + await command.ExecuteScalarAsync(); + } + } + return true; + } + catch + { + return false; + } + } + + public async Task EnsureDatabaseSchemaAsync() + { + try + { + using (var connection = new SqlConnection(_connectionString)) + { + await connection.OpenAsync(); + + // Create AppUsers table for authentication + await CreateAppUsersTableAsync(connection); + + // Create core tables + await CreateCoreTablesAsync(connection); + + // Insert default data + await InsertDefaultDataAsync(connection); + } + } + catch (Exception ex) + { + throw new Exception($"Error ensuring database schema: {ex.Message}", ex); + } + } + + private async Task CreateAppUsersTableAsync(SqlConnection connection) + { + string createUsersTable = @" + IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='AppUsers' AND xtype='U') + CREATE TABLE [AppUsers] ( + [id] INT IDENTITY(1,1) PRIMARY KEY, + [username] NVARCHAR(255) UNIQUE NOT NULL, + [password_hash] NVARCHAR(512) NOT NULL, + [password_salt] NVARCHAR(256) NOT NULL, + [created_date] DATETIME DEFAULT GETDATE(), + [last_login] DATETIME NULL, + [is_active] BIT DEFAULT 1 + )"; + + using (var command = new SqlCommand(createUsersTable, connection)) + { + await command.ExecuteNonQueryAsync(); + } + + // Create default admin user if none exists + string checkUsers = "SELECT COUNT(*) FROM AppUsers"; + using (var command = new SqlCommand(checkUsers, connection)) + { + int userCount = (int)await command.ExecuteScalarAsync(); + if (userCount == 0) + { + await CreateUserAsync(connection, "admin", "admin123"); + } + } + } + + private async Task CreateCoreTablesAsync(SqlConnection connection) + { + // files_scanned table + string createFilesScanned = @" + IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='files_scanned' AND xtype='U') + CREATE TABLE [files_scanned] ( + [id] INT IDENTITY(1,1) PRIMARY KEY, + [file_path] NVARCHAR(1024) UNIQUE NOT NULL, + [last_modified_date] DATETIME NULL, + [current_hash] VARCHAR(128) NOT NULL, + [first_scanned_date] DATETIME NOT NULL DEFAULT GETDATE(), + [last_scanned_date] DATETIME NOT NULL DEFAULT GETDATE(), + [is_sent_to_api] BIT DEFAULT 0, + [last_sent_date] DATETIME NULL, + [is_confirmed_by_api] BIT DEFAULT 0, + [last_confirmed_date] DATETIME NULL, + [is_deleted] BIT DEFAULT 0, + [deleted_date] DATETIME NULL, + [longevity_points_earned] INT DEFAULT 0 + )"; + + // scan_history table + string createScanHistory = @" + IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='scan_history' AND xtype='U') + CREATE TABLE [scan_history] ( + [id] INT IDENTITY(1,1) PRIMARY KEY, + [scan_date] DATETIME NOT NULL DEFAULT GETDATE(), + [end_date] DATETIME NULL, + [scanned_path_id] INT NULL, + [total_files_scanned] INT DEFAULT 0, + [new_files_found] INT DEFAULT 0, + [files_modified] INT DEFAULT 0, + [files_deleted] INT DEFAULT 0, + [hashes_sent_in_scan] INT DEFAULT 0, + [hashes_confirmed_in_scan] INT DEFAULT 0, + [status] NVARCHAR(50) DEFAULT 'In Progress' + )"; + + // configured_paths table + string createConfiguredPaths = @" + IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='configured_paths' AND xtype='U') + CREATE TABLE [configured_paths] ( + [id] INT IDENTITY(1,1) PRIMARY KEY, + [path] NVARCHAR(MAX) NOT NULL, + [min_fill_limit_gb] INT DEFAULT 0, + [max_fill_limit_gb] INT DEFAULT 0, + [min_fill_limit_percent] INT DEFAULT 0, + [max_fill_limit_percent] INT DEFAULT 0, + [use_limits] BIT DEFAULT 0, + [is_active] BIT DEFAULT 1 + )"; + + // program_settings table + string createProgramSettings = @" + IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='program_settings' AND xtype='U') + CREATE TABLE [program_settings] ( + [id] INT IDENTITY(1,1) PRIMARY KEY, + [setting_name] NVARCHAR(255) UNIQUE NOT NULL, + [setting_value] NVARCHAR(MAX) + )"; + + // Enhanced log table + string createLog = @" + IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='log' AND xtype='U') + CREATE TABLE [log] ( + [Entry] INT IDENTITY(1,1) PRIMARY KEY, + [Date] DATETIME DEFAULT GETDATE(), + [Message] NVARCHAR(MAX), + [Type] SMALLINT, + [username] NVARCHAR(255) NULL, + [related_path_id] INT NULL, + [event_category] NVARCHAR(50) NULL, + [details_json] NVARCHAR(MAX) NULL + )"; + + using (var command = new SqlCommand(createFilesScanned, connection)) + await command.ExecuteNonQueryAsync(); + using (var command = new SqlCommand(createScanHistory, connection)) + await command.ExecuteNonQueryAsync(); + using (var command = new SqlCommand(createConfiguredPaths, connection)) + await command.ExecuteNonQueryAsync(); + using (var command = new SqlCommand(createProgramSettings, connection)) + await command.ExecuteNonQueryAsync(); + using (var command = new SqlCommand(createLog, connection)) + await command.ExecuteNonQueryAsync(); + } + + private async Task InsertDefaultDataAsync(SqlConnection connection) + { + // Default settings + var defaultSettings = new[] + { + ("scan_interval_minutes", "60"), + ("hash_algorithm", "SHA-256"), + ("api_endpoint_url", "https://api.hashkeeper.com/v1/hashes"), + ("api_key", ""), + ("enable_api_sending", "false"), + ("batch_size", "100"), + ("min_file_size_mb", "1"), + ("max_file_size_mb", "10"), + ("application_name", "HashKeeper Pro"), + ("enable_dark_mode", "false"), + ("auto_save_settings", "true") + }; + + foreach (var (name, value) in defaultSettings) + { + string checkSetting = "SELECT COUNT(*) FROM program_settings WHERE setting_name = @name"; + using (var checkCommand = new SqlCommand(checkSetting, connection)) + { + checkCommand.Parameters.AddWithValue("@name", name); + int count = (int)await checkCommand.ExecuteScalarAsync(); + + if (count == 0) + { + string insertSetting = "INSERT INTO program_settings (setting_name, setting_value) VALUES (@name, @value)"; + using (var insertCommand = new SqlCommand(insertSetting, connection)) + { + insertCommand.Parameters.AddWithValue("@name", name); + insertCommand.Parameters.AddWithValue("@value", value); + await insertCommand.ExecuteNonQueryAsync(); + } + } + } + } + } + + private async Task CreateUserAsync(SqlConnection connection, string username, string password) + { + var salt = GenerateSalt(); + var hash = HashPassword(password, salt); + + string insertUser = @" + INSERT INTO AppUsers (username, password_hash, password_salt) + VALUES (@username, @hash, @salt)"; + + using (var command = new SqlCommand(insertUser, connection)) + { + command.Parameters.AddWithValue("@username", username); + command.Parameters.AddWithValue("@hash", hash); + command.Parameters.AddWithValue("@salt", salt); + await command.ExecuteNonQueryAsync(); + } + } + + public async Task AuthenticateUserAsync(string username, string password) + { + try + { + using (var connection = new SqlConnection(_connectionString)) + { + await connection.OpenAsync(); + + string query = @" + SELECT password_hash, password_salt + FROM AppUsers + WHERE username = @username AND is_active = 1"; + + using (var command = new SqlCommand(query, connection)) + { + command.Parameters.AddWithValue("@username", username); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + string storedHash = reader["password_hash"].ToString(); + string salt = reader["password_salt"].ToString(); + + string computedHash = HashPassword(password, salt); + + if (storedHash == computedHash) + { + // Update last login + reader.Close(); + string updateLogin = "UPDATE AppUsers SET last_login = GETDATE() WHERE username = @username"; + using (var updateCommand = new SqlCommand(updateLogin, connection)) + { + updateCommand.Parameters.AddWithValue("@username", username); + await updateCommand.ExecuteNonQueryAsync(); + } + return true; + } + } + } + } + } + return false; + } + catch + { + return false; + } + } + + public async Task LogEventAsync(string eventCategory, string message, LogType logType, string username = null, int? relatedPathId = null, string detailsJson = null) + { + try + { + using (var connection = new SqlConnection(_connectionString)) + { + await connection.OpenAsync(); + + string query = @" + INSERT INTO log (Message, Type, username, related_path_id, event_category, details_json) + VALUES (@message, @type, @username, @pathId, @category, @details)"; + + using (var command = new SqlCommand(query, connection)) + { + command.Parameters.AddWithValue("@message", message); + command.Parameters.AddWithValue("@type", (int)logType); + command.Parameters.AddWithValue("@username", (object)username ?? DBNull.Value); + command.Parameters.AddWithValue("@pathId", (object)relatedPathId ?? DBNull.Value); + command.Parameters.AddWithValue("@category", (object)eventCategory ?? DBNull.Value); + command.Parameters.AddWithValue("@details", (object)detailsJson ?? DBNull.Value); + + await command.ExecuteNonQueryAsync(); + } + } + } + catch + { + // Silent fail for logging to prevent recursive errors + } + } + + private string GenerateSalt() + { + byte[] saltBytes = new byte[32]; + using (var rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(saltBytes); + } + return Convert.ToBase64String(saltBytes); + } + + private string HashPassword(string password, string salt) + { + using (var pbkdf2 = new Rfc2898DeriveBytes(password, Convert.FromBase64String(salt), 10000)) + { + byte[] hash = pbkdf2.GetBytes(64); + return Convert.ToBase64String(hash); + } + } + + // New HashKeeper Pro methods + public async Task> GetUnsentHashesAsync(int batchSize = 100) + { + var files = new List(); + + using (var connection = new SqlConnection(_connectionString)) + { + await connection.OpenAsync(); + + string query = @" + SELECT TOP (@batchSize) id, file_path, current_hash, first_scanned_date, last_scanned_date + FROM files_scanned + WHERE is_sent_to_api = 0 AND is_deleted = 0 + ORDER BY first_scanned_date ASC"; + + using (var command = new SqlCommand(query, connection)) + { + command.Parameters.AddWithValue("@batchSize", batchSize); + using (var reader = await command.ExecuteReaderAsync()) + { + while (await reader.ReadAsync()) + { + files.Add(new FileRecord + { + Id = reader.GetInt32(IdColumnName), + FilePath = reader.GetString("file_path"), + Hash = reader.GetString("current_hash"), + FirstScannedDate = reader.GetDateTime("first_scanned_date"), + LastScannedDate = reader.GetDateTime("last_scanned_date") + }); + } + } + } + } + + return files; + } + + public async Task MarkHashesSentAsync(List hashes) + { + try + { + using (var connection = new SqlConnection(_connectionString)) + { + await connection.OpenAsync(); + using (var transaction = connection.BeginTransaction()) + { + try + { + foreach (string hash in hashes) + { + string updateQuery = @" + UPDATE files_scanned + SET is_sent_to_api = 1, last_sent_date = GETDATE() + WHERE current_hash = @hash"; + + using (var command = new SqlCommand(updateQuery, connection, transaction)) + { + command.Parameters.AddWithValue("@hash", hash); + await command.ExecuteNonQueryAsync(); + } + } + + transaction.Commit(); + return true; + } + catch + { + transaction.Rollback(); + return false; + } + } + } + } + catch + { + return false; + } + } + + public async Task MarkHashConfirmedAsync(string hash) + { + try + { + using (var connection = new SqlConnection(_connectionString)) + { + await connection.OpenAsync(); + + string updateQuery = @" + UPDATE files_scanned + SET is_confirmed_by_api = 1, last_confirmed_date = GETDATE() + WHERE current_hash = @hash"; + + using (var command = new SqlCommand(updateQuery, connection)) + { + command.Parameters.AddWithValue("@hash", hash); + await command.ExecuteNonQueryAsync(); + } + + return true; + } + } + catch + { + return false; + } + } + + public async Task GetDashboardStatsAsync() + { + var stats = new DashboardStats(); + + using (var connection = new SqlConnection(_connectionString)) + { + await connection.OpenAsync(); + + // Total hashes + string totalQuery = "SELECT COUNT(*) FROM files_scanned WHERE is_deleted = 0"; + using (var command = new SqlCommand(totalQuery, connection)) + { + stats.TotalHashes = (int)await command.ExecuteScalarAsync(); + } + + // New hashes (last 24 hours) + string newQuery = @" + SELECT COUNT(*) FROM files_scanned + WHERE is_deleted = 0 AND first_scanned_date >= DATEADD(day, -1, GETDATE())"; + using (var command = new SqlCommand(newQuery, connection)) + { + stats.NewHashes = (int)await command.ExecuteScalarAsync(); + } + + // Sent hashes + string sentQuery = "SELECT COUNT(*) FROM files_scanned WHERE is_sent_to_api = 1 AND is_deleted = 0"; + using (var command = new SqlCommand(sentQuery, connection)) + { + stats.SentHashes = (int)await command.ExecuteScalarAsync(); + } + + // Confirmed hashes + string confirmedQuery = "SELECT COUNT(*) FROM files_scanned WHERE is_confirmed_by_api = 1 AND is_deleted = 0"; + using (var command = new SqlCommand(confirmedQuery, connection)) + { + stats.ConfirmedHashes = (int)await command.ExecuteScalarAsync(); + } + } + + return stats; + } + + // Legacy compatibility methods + public DataTable GetHashes() + { + DataTable hashes = new DataTable(); + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + string query = @" + SELECT file_path as Path, current_hash as Hash, last_modified_date as Updated + FROM files_scanned + WHERE is_deleted = 0"; + + using (var command = new SqlCommand(query, connection)) + { + using (var adapter = new SqlDataAdapter(command)) + { + adapter.Fill(hashes); + } + } + } + return hashes; + } + + public bool HashExists(string hash) + { + using (var connection = new SqlConnection(_connectionString)) + { + try + { + connection.Open(); + string checkQuery = "SELECT COUNT(*) FROM files_scanned WHERE current_hash = @Hash AND is_deleted = 0"; + + using (var command = new SqlCommand(checkQuery, connection)) + { + command.Parameters.AddWithValue("@Hash", hash.ToUpperInvariant()); + int count = (int)command.ExecuteScalar(); + return count > 0; + } + } + catch + { + return false; + } + } + } + + public bool InsertHash(string path, string hash) + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + using (var transaction = connection.BeginTransaction()) + { + try + { + DateTime lastModified = File.Exists(path) ? File.GetLastWriteTime(path) : DateTime.Now; + + string insertQuery = @" + INSERT INTO files_scanned (file_path, current_hash, last_modified_date, first_scanned_date, last_scanned_date) + VALUES (@Path, @Hash, @LastModified, GETDATE(), GETDATE())"; + + using (var command = new SqlCommand(insertQuery, connection, transaction)) + { + command.Parameters.AddWithValue("@Path", path); + command.Parameters.AddWithValue("@Hash", hash.ToUpperInvariant()); + command.Parameters.AddWithValue("@LastModified", lastModified); + command.ExecuteNonQuery(); + } + transaction.Commit(); + return true; + } + catch + { + transaction.Rollback(); + return false; + } + } + } + } + + public bool UpdateHash(string path, string hash) + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + using (var transaction = connection.BeginTransaction()) + { + try + { + DateTime lastModified = File.Exists(path) ? File.GetLastWriteTime(path) : DateTime.Now; + + string updateQuery = @" + UPDATE files_scanned + SET file_path = @Path, last_modified_date = @LastModified, last_scanned_date = GETDATE(), is_sent_to_api = 0 + WHERE current_hash = @Hash"; + + using (var command = new SqlCommand(updateQuery, connection, transaction)) + { + command.Parameters.AddWithValue("@Path", path); + command.Parameters.AddWithValue("@Hash", hash.ToUpperInvariant()); + command.Parameters.AddWithValue("@LastModified", lastModified); + command.ExecuteNonQuery(); + } + transaction.Commit(); + return true; + } + catch + { + transaction.Rollback(); + return false; + } + } + } + } + + public void InsertLog(string message, LogType type = LogType.INFO) + { + try + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + string query = "INSERT INTO log (Message, Type) VALUES (@Message, @Type)"; + using (var command = new SqlCommand(query, connection)) + { + command.Parameters.AddWithValue("@Message", message); + command.Parameters.AddWithValue("@Type", (int)type); + command.ExecuteNonQuery(); + } + } + } + catch + { + // Silent fail for logging + } + } + + public DataTable GetLogs(string query = null) + { + DataTable logs = new DataTable(); + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + string sql = string.IsNullOrEmpty(query) ? "SELECT * FROM log ORDER BY Date DESC" : query; + using (var command = new SqlCommand(sql, connection)) + { + using (var adapter = new SqlDataAdapter(command)) + { + adapter.Fill(logs); + } + } + } + return logs; + } + } + + public class FileRecord + { + public int Id { get; set; } + public string FilePath { get; set; } + public string Hash { get; set; } + public DateTime FirstScannedDate { get; set; } + public DateTime LastScannedDate { get; set; } + } + + public class DashboardStats + { + public int TotalHashes { get; set; } + public int NewHashes { get; set; } + public int SentHashes { get; set; } + public int ConfirmedHashes { get; set; } + } +} \ No newline at end of file diff --git a/BSHash/BSHash/Manager/FileScanner.cs b/BSHash/BSHash/Manager/FileScanner.cs new file mode 100644 index 0000000..73ab849 --- /dev/null +++ b/BSHash/BSHash/Manager/FileScanner.cs @@ -0,0 +1,426 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using System.Security.Cryptography; +using System.Text; +using BSHash.Manager; + +namespace BSHash.Manager +{ + public class FileScanner + { + private readonly Database _database; + private readonly List _activeScanTokens; + private readonly object _lockObject = new object(); + + public event Action ProgressUpdated; + public event Action StatusUpdated; + + public FileScanner(Database database) + { + _database = database; + _activeScanTokens = new List(); + } + + public async Task ScanPathAsync(string path, IProgress progress = null, CancellationToken cancellationToken = default) + { + var result = new ScanResult + { + ScanStartTime = DateTime.Now, + ScannedPath = path + }; + + try + { + if (!Directory.Exists(path)) + { + result.Status = ScanStatus.Failed; + result.ErrorMessage = $"Directory does not exist: {path}"; + return result; + } + + StatusUpdated?.Invoke($"Starting scan of {path}"); + await _database.LogEventAsync("Scan", $"Starting scan of path: {path}", LogType.INFO, UserSession.CurrentUser); + + // Get all files in directory recursively + var files = GetAllFiles(path, cancellationToken); + result.TotalFiles = files.Count; + + StatusUpdated?.Invoke($"Found {files.Count} files to process"); + + for (int i = 0; i < files.Count; i++) + { + if (cancellationToken.IsCancellationRequested) + { + result.Status = ScanStatus.Cancelled; + break; + } + + string filePath = files[i]; + + try + { + var fileResult = await ProcessFileAsync(filePath, cancellationToken); + + if (fileResult.IsNew) + result.NewFiles++; + else if (fileResult.IsModified) + result.ModifiedFiles++; + + result.ProcessedFiles++; + + // Report progress + var progressReport = new ScanProgress + { + TotalFiles = result.TotalFiles, + ProcessedFiles = result.ProcessedFiles, + NewFiles = result.NewFiles, + ModifiedFiles = result.ModifiedFiles, + CurrentFile = filePath, + PercentComplete = (double)result.ProcessedFiles / result.TotalFiles * 100 + }; + + progress?.Report(progressReport); + ProgressUpdated?.Invoke(progressReport); + } + catch (Exception ex) + { + result.ErrorFiles++; + await _database.LogEventAsync("Scan", $"Error processing file {filePath}: {ex.Message}", LogType.ERROR, UserSession.CurrentUser); + } + } + + // Check for deleted files + await CheckForDeletedFilesAsync(path, result); + + result.ScanEndTime = DateTime.Now; + result.Status = cancellationToken.IsCancellationRequested ? ScanStatus.Cancelled : ScanStatus.Completed; + + StatusUpdated?.Invoke($"Scan completed. Processed {result.ProcessedFiles} files, {result.NewFiles} new, {result.ModifiedFiles} modified, {result.DeletedFiles} deleted"); + await _database.LogEventAsync("Scan", $"Scan completed: {result.ProcessedFiles} files processed", LogType.INFO, UserSession.CurrentUser); + + return result; + } + catch (Exception ex) + { + result.Status = ScanStatus.Failed; + result.ErrorMessage = ex.Message; + result.ScanEndTime = DateTime.Now; + + await _database.LogEventAsync("Scan", $"Scan failed: {ex.Message}", LogType.ERROR, UserSession.CurrentUser); + return result; + } + } + + private List GetAllFiles(string path, CancellationToken cancellationToken) + { + var files = new List(); + var directories = new Queue(); + directories.Enqueue(path); + + while (directories.Count > 0 && !cancellationToken.IsCancellationRequested) + { + string currentDir = directories.Dequeue(); + + try + { + // Add files from current directory + string[] dirFiles = Directory.GetFiles(currentDir); + foreach (string file in dirFiles) + { + if (ShouldProcessFile(file)) + { + files.Add(file); + } + } + + // Add subdirectories to queue + string[] subDirs = Directory.GetDirectories(currentDir); + foreach (string subDir in subDirs) + { + if (ShouldProcessDirectory(subDir)) + { + directories.Enqueue(subDir); + } + } + } + catch (UnauthorizedAccessException) + { + // Skip directories we can't access + continue; + } + catch (DirectoryNotFoundException) + { + // Skip directories that no longer exist + continue; + } + } + + return files; + } + + private bool ShouldProcessFile(string filePath) + { + try + { + var fileInfo = new FileInfo(filePath); + + // Skip system files and hidden files + if (fileInfo.Attributes.HasFlag(FileAttributes.System) || + fileInfo.Attributes.HasFlag(FileAttributes.Hidden)) + return false; + + // Skip very small files (less than 1KB) + if (fileInfo.Length < 1024) + return false; + + // Skip temporary files + string extension = fileInfo.Extension.ToLower(); + string[] skipExtensions = { ".tmp", ".temp", ".log", ".lock" }; + if (Array.Exists(skipExtensions, ext => ext == extension)) + return false; + + return true; + } + catch + { + return false; + } + } + + private bool ShouldProcessDirectory(string dirPath) + { + string dirName = Path.GetFileName(dirPath).ToLower(); + + // Skip system directories + string[] skipDirs = { + "$recycle.bin", "system volume information", "temp", + "tmp", "cache", ".git", ".svn", "node_modules" + }; + + return !Array.Exists(skipDirs, skipDir => skipDir == dirName); + } + + private async Task ProcessFileAsync(string filePath, CancellationToken cancellationToken) + { + var result = new FileProcessResult { FilePath = filePath }; + + try + { + // Calculate hash + string hash = await CalculateFileHashAsync(filePath, cancellationToken); + result.Hash = hash; + + // Check if file exists in database + bool exists = _database.HashExists(hash); + + if (!exists) + { + // New file + bool inserted = _database.InsertHash(filePath, hash); + result.IsNew = inserted; + } + else + { + // Existing file - check if path has changed + bool updated = _database.UpdateHash(filePath, hash); + result.IsModified = updated; + } + + return result; + } + catch (Exception ex) + { + result.HasError = true; + result.ErrorMessage = ex.Message; + return result; + } + } + + private async Task CalculateFileHashAsync(string filePath, CancellationToken cancellationToken) + { + using (var sha256 = SHA256.Create()) + { + using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 8192, useAsync: true)) + { + byte[] buffer = new byte[8192]; + int bytesRead; + + while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0) + { + sha256.TransformBlock(buffer, 0, bytesRead, null, 0); + } + + sha256.TransformFinalBlock(new byte[0], 0, 0); + byte[] hash = sha256.Hash; + + StringBuilder sb = new StringBuilder(); + foreach (byte b in hash) + { + sb.Append(b.ToString("x2")); + } + + return sb.ToString().ToUpperInvariant(); + } + } + } + + private async Task CheckForDeletedFilesAsync(string scannedPath, ScanResult result) + { + try + { + // This would require tracking which files were scanned vs what's in the database + // For now, we'll implement a basic version that checks if files in the database still exist + + var hashes = _database.GetHashes(); + foreach (System.Data.DataRow row in hashes.Rows) + { + string filePath = row["Path"].ToString(); + + // Only check files that should be in the scanned path + if (filePath.StartsWith(scannedPath, StringComparison.OrdinalIgnoreCase)) + { + if (!File.Exists(filePath)) + { + // File has been deleted + // We would need to implement MarkFileAsDeleted in Database class + result.DeletedFiles++; + } + } + } + } + catch (Exception ex) + { + await _database.LogEventAsync("Scan", $"Error checking for deleted files: {ex.Message}", LogType.WARNING, UserSession.CurrentUser); + } + } + + public async Task StartContinuousScanAsync(List paths, TimeSpan interval, CancellationToken cancellationToken) + { + await _database.LogEventAsync("Scanner", "Started continuous scanning", LogType.INFO, UserSession.CurrentUser); + + while (!cancellationToken.IsCancellationRequested) + { + foreach (string path in paths) + { + if (cancellationToken.IsCancellationRequested) + break; + + try + { + StatusUpdated?.Invoke($"Scanning {path}..."); + await ScanPathAsync(path, null, cancellationToken); + } + catch (Exception ex) + { + await _database.LogEventAsync("Scanner", $"Error in continuous scan of {path}: {ex.Message}", LogType.ERROR, UserSession.CurrentUser); + } + } + + // Wait for the specified interval + try + { + await Task.Delay(interval, cancellationToken); + } + catch (TaskCanceledException) + { + break; + } + } + + await _database.LogEventAsync("Scanner", "Stopped continuous scanning", LogType.INFO, UserSession.CurrentUser); + } + + public void StopAllScans() + { + lock (_lockObject) + { + foreach (var tokenSource in _activeScanTokens) + { + try + { + tokenSource.Cancel(); + } + catch { } + } + _activeScanTokens.Clear(); + } + } + + public CancellationTokenSource StartScan(string path, IProgress progress = null) + { + var tokenSource = new CancellationTokenSource(); + + lock (_lockObject) + { + _activeScanTokens.Add(tokenSource); + } + + Task.Run(async () => + { + try + { + await ScanPathAsync(path, progress, tokenSource.Token); + } + finally + { + lock (_lockObject) + { + _activeScanTokens.Remove(tokenSource); + } + } + }); + + return tokenSource; + } + } + + public class ScanResult + { + public DateTime ScanStartTime { get; set; } + public DateTime ScanEndTime { get; set; } + public string ScannedPath { get; set; } + public ScanStatus Status { get; set; } + public string ErrorMessage { get; set; } + + public int TotalFiles { get; set; } + public int ProcessedFiles { get; set; } + public int NewFiles { get; set; } + public int ModifiedFiles { get; set; } + public int DeletedFiles { get; set; } + public int ErrorFiles { get; set; } + + public TimeSpan Duration => ScanEndTime - ScanStartTime; + } + + public class ScanProgress + { + public int TotalFiles { get; set; } + public int ProcessedFiles { get; set; } + public int NewFiles { get; set; } + public int ModifiedFiles { get; set; } + public string CurrentFile { get; set; } + public double PercentComplete { get; set; } + } + + public class FileProcessResult + { + public string FilePath { get; set; } + public string Hash { get; set; } + public bool IsNew { get; set; } + public bool IsModified { get; set; } + public bool HasError { get; set; } + public string ErrorMessage { get; set; } + } + + public enum ScanStatus + { + NotStarted, + Running, + Completed, + Cancelled, + Failed + } +} \ No newline at end of file diff --git a/BSHash/BSHash/Manager/Logger.cs b/BSHash/BSHash/Manager/Logger.cs new file mode 100644 index 0000000..6875061 --- /dev/null +++ b/BSHash/BSHash/Manager/Logger.cs @@ -0,0 +1,379 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Text.Json; + +namespace BSHash +{ + public enum LogType + { + DEBUG = 0, + INFO = 1, + WARN = 2, + ERROR = 3, + FATAL = 4, + TEST = 5 + } + + public enum LogStatus + { + ATTESA, + PREPARAZIONE, + ELABORAZIONE, + FERMATA, + COMPLETATO, + ERRORE + } + + public enum EventCategory + { + Login, + Scan, + API, + FileManagement, + Database, + System + } + + public class Logger + { + private Database databaseHelper; + private System.Windows.Forms.TextBox logTextBox; + private string currentUsername; + private int? currentPathId; + + public Logger(System.Windows.Forms.TextBox logTextBox, Database databaseHelper) + { + this.logTextBox = logTextBox; + this.databaseHelper = databaseHelper; + } + + public void SetContext(string username, int? pathId = null) + { + currentUsername = username; + currentPathId = pathId; + } + + public void Log(string message, LogType type = LogType.INFO) + { + LogDetailed(message, type, EventCategory.System, null); + } + + public void LogDetailed(string message, LogType type = LogType.INFO, EventCategory category = EventCategory.System, object details = null) + { + try + { + string detailsJson = null; + if (details != null) + { + try + { + detailsJson = JsonSerializer.Serialize(details); + } + catch + { + detailsJson = details.ToString(); + } + } + + databaseHelper.InsertLogDetailed(message, type, currentUsername, currentPathId, category.ToString(), detailsJson); + } + catch (Exception ex) + { + // Fallback to basic logging if detailed logging fails + try + { + databaseHelper.InsertLog(message, type); + } + catch + { + // If all logging fails, at least try to write to debug output + System.Diagnostics.Debug.WriteLine($"[{type}] {message}: {ex.Message}"); + } + } + } + + public void LogLogin(string username, bool success, string details = null) + { + SetContext(username); + + var loginDetails = new + { + success = success, + timestamp = DateTime.Now, + details = details, + machine = Environment.MachineName + }; + + LogDetailed( + success ? $"Login riuscito per utente: {username}" : $"Login fallito per utente: {username}", + success ? LogType.INFO : LogType.WARN, + EventCategory.Login, + loginDetails + ); + } + + public void LogScanStart(string path, int pathId, int totalFiles) + { + SetContext(currentUsername, pathId); + + var scanDetails = new + { + scanned_path = path, + total_files = totalFiles, + start_time = DateTime.Now + }; + + LogDetailed( + $"Avvio scansione percorso: {path} ({totalFiles} file da processare)", + LogType.INFO, + EventCategory.Scan, + scanDetails + ); + } + + public void LogScanComplete(string path, int totalFiles, int newFiles, int modifiedFiles, int deletedFiles) + { + var scanDetails = new + { + scanned_path = path, + total_files = totalFiles, + new_files = newFiles, + modified_files = modifiedFiles, + deleted_files = deletedFiles, + end_time = DateTime.Now + }; + + LogDetailed( + $"Scansione completata: {path} - {totalFiles} file processati, {newFiles} nuovi, {modifiedFiles} modificati, {deletedFiles} eliminati", + LogType.INFO, + EventCategory.Scan, + scanDetails + ); + } + + public void LogFileProcessed(string filePath, string hash, bool isNew, bool isModified) + { + var fileDetails = new + { + file_path = filePath, + hash = hash, + is_new = isNew, + is_modified = isModified, + timestamp = DateTime.Now + }; + + LogDetailed( + $"File processato: {filePath} - Hash: {hash?.Substring(0, 8)}...", + LogType.DEBUG, + EventCategory.FileManagement, + fileDetails + ); + } + + public void LogApiSubmission(int hashCount, bool success, string apiResponse = null) + { + var apiDetails = new + { + hash_count = hashCount, + success = success, + api_response = apiResponse, + timestamp = DateTime.Now + }; + + LogDetailed( + success ? $"Invio API riuscito: {hashCount} hash inviati" : $"Invio API fallito: {hashCount} hash", + success ? LogType.INFO : LogType.ERROR, + EventCategory.API, + apiDetails + ); + } + + public void LogApiConfirmation(string hash, bool confirmed) + { + var confirmDetails = new + { + hash = hash, + confirmed = confirmed, + timestamp = DateTime.Now + }; + + LogDetailed( + confirmed ? $"Hash confermato: {hash?.Substring(0, 8)}..." : $"Hash rifiutato: {hash?.Substring(0, 8)}...", + confirmed ? LogType.INFO : LogType.WARN, + EventCategory.API, + confirmDetails + ); + } + + public void LogDatabaseOperation(string operation, bool success, string details = null) + { + var dbDetails = new + { + operation = operation, + success = success, + details = details, + timestamp = DateTime.Now + }; + + LogDetailed( + $"Operazione database: {operation} - {(success ? "Successo" : "Fallimento")}", + success ? LogType.INFO : LogType.ERROR, + EventCategory.Database, + dbDetails + ); + } + + public void LogEsecuzioneExecute(LogStatus stato, long spazioscansionato, long scansionati, int errori, int warning) + { + StringBuilder log = new StringBuilder(); + + log.Append("Stato procedura: " + LogStatusToString(stato) + Environment.NewLine); + log.Append("Totale spazio scansionato: " + ConvertBytesToReadableSize(spazioscansionato) + Environment.NewLine); + log.Append("Totale file scansionati: " + scansionati + Environment.NewLine); + log.Append("Errori: " + errori + Environment.NewLine); + log.Append("Warning: " + warning + Environment.NewLine); + + SetLogTextBox(log.ToString()); + + // Also log to database + var executionDetails = new + { + status = stato.ToString(), + space_scanned = spazioscansionato, + files_scanned = scansionati, + errors = errori, + warnings = warning + }; + + LogDetailed( + $"Stato esecuzione: {LogStatusToString(stato)}", + LogType.INFO, + EventCategory.System, + executionDetails + ); + } + + public void LogDispositivoFill(LogStatus stato, int creati, int salvati, long spaziototale, long spazioriempito, int errori, int warning) + { + StringBuilder log = new StringBuilder(); + + log.Append("Stato procedura: " + LogStatusToString(stato) + Environment.NewLine); + log.Append("Spazio totale da riempire: " + ConvertBytesToReadableSize(spaziototale) + Environment.NewLine); + log.Append("Spazio occupato: " + ConvertBytesToReadableSize(spazioriempito) + Environment.NewLine); + log.Append("Totale file generati: " + creati + Environment.NewLine); + log.Append("Files salvati: " + salvati + Environment.NewLine); + log.Append("Errori: " + errori + Environment.NewLine); + log.Append("Warning: " + warning + Environment.NewLine); + + SetLogTextBox(log.ToString()); + + // Also log to database + var fillDetails = new + { + status = stato.ToString(), + total_space = spaziototale, + filled_space = spazioriempito, + files_created = creati, + files_saved = salvati, + errors = errori, + warnings = warning + }; + + LogDetailed( + $"Riempimento dispositivo: {LogStatusToString(stato)}", + LogType.INFO, + EventCategory.FileManagement, + fillDetails + ); + } + + public void LogDispositivoCheck(LogStatus stato, int totale, int elaborati, int inseriti, int presenti, int errori, int warning) + { + StringBuilder log = new StringBuilder(); + + log.Append("Stato procedura: " + LogStatusToString(stato) + Environment.NewLine); + log.Append("Totale da scansionare: " + totale + Environment.NewLine); + log.Append("Files scansionati: " + elaborati + Environment.NewLine); + log.Append("Files aggiornati: " + presenti + Environment.NewLine); + log.Append("Files inseriti: " + inseriti + Environment.NewLine); + log.Append("Errori: " + errori + Environment.NewLine); + log.Append("Warning: " + warning + Environment.NewLine); + + SetLogTextBox(log.ToString()); + + // Also log to database + var checkDetails = new + { + status = stato.ToString(), + total_files = totale, + processed_files = elaborati, + inserted_files = inseriti, + updated_files = presenti, + errors = errori, + warnings = warning + }; + + LogDetailed( + $"Controllo dispositivo: {LogStatusToString(stato)}", + LogType.INFO, + EventCategory.FileManagement, + checkDetails + ); + } + + public string LogStatusToString(LogStatus status) + { + switch (status) + { + case LogStatus.ATTESA: + return "In attesa di avvio"; + case LogStatus.PREPARAZIONE: + return "Preparazione per l'elaborazione..."; + case LogStatus.ELABORAZIONE: + return "In elaborazione..."; + case LogStatus.FERMATA: + return "Stoppata dall'utente"; + case LogStatus.COMPLETATO: + return "Completato"; + case LogStatus.ERRORE: + return "Errore"; + default: + return "In attesa di avvio"; + } + } + + public void SetLogTextBox(string log) + { + if (logTextBox != null) + { + if (logTextBox.InvokeRequired) + { + logTextBox.Invoke(new Action(() => logTextBox.Text = log + Environment.NewLine)); + } + else + { + logTextBox.Text = log + Environment.NewLine; + } + } + } + + public static string ConvertBytesToReadableSize(long bytes) + { + string[] sizes = { "B", "KB", "MB", "GB", "TB" }; + double len = bytes; + int order = 0; + + while (len >= 1024 && order < sizes.Length - 1) + { + order++; + len = len / 1024; + } + + return $"{len:0.##} {sizes[order]}"; + } + } +} diff --git a/BSHash/BSHash/Manager/Network.cs b/BSHash/BSHash/Manager/Network.cs new file mode 100644 index 0000000..34aee4d --- /dev/null +++ b/BSHash/BSHash/Manager/Network.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace BSHash +{ + public class Network + { + private readonly HttpClient _httpClient; + private Logger _logger; + private ApiManager _apiManager; + private static readonly Random _random = new Random(); + + // Costanti per i possibili stati di risposta + public static string OK = "OK"; + public static string TIMEOUT = "TIMEOUT"; + public static string ERROR = "ERROR"; + + public Network(Logger logger) + { + _httpClient = new HttpClient(); + _logger = logger; + } + + public Network(Logger logger, Database database) : this(logger) + { + _apiManager = new ApiManager(database, logger); + } + + public async Task SendDataHash(string hash) + { + try + { + _logger.Log("Invio dati hash...", LogType.INFO); + + // If ApiManager is available, use it for real API calls + if (_apiManager != null) + { + var result = await _apiManager.SubmitPendingHashesAsync(); + if (result.Status == "Completed" || result.Status == "Disabled") + { + _logger.Log($"Invio hash completato: {result.Message}", LogType.INFO); + return OK; + } + else + { + _logger.Log($"Errore invio hash: {result.Message}", LogType.ERROR); + return ERROR; + } + } + + // Fallback to simulation for testing + /* + var content = new StringContent(data, Encoding.UTF8, "application/json"); + HttpResponseMessage response = await _httpClient.PostAsync(url, content); + + response.EnsureSuccessStatusCode(); + + string responseData = await response.Content.ReadAsStringAsync(); + return responseData; + */ + + //Simula l'attesa di una risposta con un tempo randomico + //int delay = _random.Next(1, 5000); // da 1ms a 5s + int delay = _random.Next(100, 1000); // da 100ms a 1s per testing + + _logger.Log("Dati inviati. Elaborazione...", LogType.INFO); + + await Task.Delay(delay); + + _logger.Log($"Tempo di chiamata: {delay}ms", LogType.INFO); + + return OK; + } + catch (Exception ex) + { + // Logga o gestisci l'eccezione come necessario + _logger.Log("Errore della chiamata: " + ex.Message, LogType.ERROR); + return $"Error: {ex.Message}"; + } + } + + public async Task GetDataHash(string hash) + { + try + { + _logger.Log("Ricezione risposta hash...", LogType.INFO); + + // If ApiManager is available, check API health + if (_apiManager != null) + { + var healthResult = await _apiManager.CheckApiHealthAsync(); + if (healthResult.IsHealthy) + { + _logger.Log("API esterna raggiungibile e funzionante", LogType.INFO); + return OK; + } + else + { + _logger.Log($"API esterna non raggiungibile: {healthResult.Message}", LogType.WARN); + return ERROR; + } + } + + // Fallback to simulation + /* + HttpResponseMessage response = await _httpClient.GetAsync(url); + + response.EnsureSuccessStatusCode(); + + string responseData = await response.Content.ReadAsStringAsync(); + return responseData; + */ + + // Simula l'attesa di una risposta con un tempo randomico + //int delay = _random.Next(1, 5000); // da 1ms a 5s + int delay = _random.Next(100, 800); // da 100ms a 800ms per testing + + _logger.Log("Risposta ricevuta. Elaborazione...", LogType.INFO); + + await Task.Delay(delay); + + _logger.Log($"Tempo di risposta: {delay}ms", LogType.INFO); + + return OK; + } + catch (Exception ex) + { + // Logga o gestisci l'eccezione come necessario + _logger.Log("Errore della chiamata: " + ex.Message, LogType.ERROR); + return $"Error: {ex.Message}"; + } + } + + // New method for HashKeeper Pro API integration + public async Task SubmitHashesAsync() + { + if (_apiManager == null) + { + _logger.Log("ApiManager non inizializzato", LogType.ERROR); + return ERROR; + } + + try + { + var result = await _apiManager.SubmitPendingHashesAsync(); + + if (result.Status == "Completed") + { + _logger.Log($"Batch di hash inviato con successo: {result.SuccessfulSubmissions} hash inviati", LogType.INFO); + return OK; + } + else if (result.Status == "Disabled") + { + _logger.Log("Invio API disabilitato nelle impostazioni", LogType.INFO); + return OK; + } + else + { + _logger.Log($"Errore durante l'invio batch: {result.Message}", LogType.ERROR); + return ERROR; + } + } + catch (Exception ex) + { + _logger.Log($"Errore imprevisto durante l'invio hash: {ex.Message}", LogType.ERROR); + return ERROR; + } + } + + public async Task TestApiConnectionAsync() + { + if (_apiManager == null) + return false; + + try + { + var healthResult = await _apiManager.CheckApiHealthAsync(); + _logger.Log($"Test connessione API: {(healthResult.IsHealthy ? "SUCCESSO" : "FALLITO")} - {healthResult.Message}", + healthResult.IsHealthy ? LogType.INFO : LogType.ERROR); + return healthResult.IsHealthy; + } + catch (Exception ex) + { + _logger.Log($"Errore test connessione API: {ex.Message}", LogType.ERROR); + return false; + } + } + + public void Dispose() + { + _httpClient?.Dispose(); + _apiManager?.Dispose(); + } + } +} diff --git a/BSHash/BSHash/Storage.cs b/BSHash/BSHash/Manager/Storage.cs similarity index 81% rename from BSHash/BSHash/Storage.cs rename to BSHash/BSHash/Manager/Storage.cs index dc5fe50..ffc9d5b 100644 --- a/BSHash/BSHash/Storage.cs +++ b/BSHash/BSHash/Manager/Storage.cs @@ -223,14 +223,20 @@ namespace BSHash { try { - string fileName = Path.Combine(path, Guid.NewGuid() + ".bs"); - byte[] data = new byte[sectorSize]; + // Generate filename with timestamp and GUID for uniqueness + string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss"); + string fileName = Path.Combine(path, $"hashkeeper_{timestamp}_{Guid.NewGuid():N}.hkp"); + + // Create file with random content (1MB to 10MB range for optimal hash count) + int minSize = 1024 * 1024; // 1 MB + int maxSize = 10 * 1024 * 1024; // 10 MB + int fileSize = _random.Next(minSize, maxSize); + + byte[] data = new byte[fileSize]; _random.NextBytes(data); await WriteAllBytesAsync(fileName, data); - _logger.Log($"Creato file {fileName}.", LogType.INFO); - - + _logger.Log($"Creato file {fileName} ({ConvertBytesToReadableSize(fileSize)})", LogType.INFO); return data.Length; } @@ -241,6 +247,21 @@ namespace BSHash } } + private string ConvertBytesToReadableSize(long bytes) + { + string[] sizes = { "B", "KB", "MB", "GB", "TB" }; + double len = bytes; + int order = 0; + + while (len >= 1024 && order < sizes.Length - 1) + { + order++; + len = len / 1024; + } + + return $"{len:0.##} {sizes[order]}"; + } + private async Task WriteAllBytesAsync(string path, byte[] bytes) { using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true)) @@ -251,12 +272,59 @@ namespace BSHash private int GetSectorSize(string drive) { - // Assuming a default sector size of 1024 * 1024 * 128 bytes (128 MB) - // Total 127.831.113.728 bytes - // : 128 = 998.680.576 - // : 1024 = 975.274 - // : 1024 = 952 - return 1024 * 128; + // For HashKeeper Pro, use optimal file sizes between 1MB and 10MB + // This maximizes the number of unique hashes without overloading the filesystem + + // Generate random size between 1MB and 10MB + int minSize = 1024 * 1024; // 1 MB + int maxSize = 10 * 1024 * 1024; // 10 MB + + return _random.Next(minSize, maxSize); + } + + // Funzione ricorsiva per ottenere tutti i file, saltando cartelle protette + private List GetAllFilesSafe(string rootPath, List excludeDirs, CancellationToken cancellationToken) + { + var files = new List(); + try + { + foreach (var dir in Directory.GetDirectories(rootPath)) + { + if (cancellationToken.IsCancellationRequested) + break; + + string dirName = Path.GetFileName(dir).ToLowerInvariant(); + if (excludeDirs.Contains(dirName)) + continue; + try + { + files.AddRange(GetAllFilesSafe(dir, excludeDirs, cancellationToken)); + } + catch (UnauthorizedAccessException ex) + { + _logger.Log($"Accesso negato alla cartella '{dir}': {ex.Message}", LogType.WARN); + } + catch (Exception ex) + { + _logger.Log($"Errore durante l'accesso alla cartella '{dir}': {ex.Message}", LogType.WARN); + } + } + foreach (var file in Directory.GetFiles(rootPath)) + { + if (cancellationToken.IsCancellationRequested) + break; + files.Add(file); + } + } + catch (UnauthorizedAccessException ex) + { + _logger.Log($"Accesso negato alla cartella '{rootPath}': {ex.Message}", LogType.WARN); + } + catch (Exception ex) + { + _logger.Log($"Errore durante l'accesso alla cartella '{rootPath}': {ex.Message}", LogType.WARN); + } + return files; } public async Task CheckFilesAsync(string path, System.Windows.Forms.ProgressBar progressBar, CancellationToken cancellationToken, System.Windows.Forms.Button startButton, System.Windows.Forms.Button stopButton) @@ -272,25 +340,27 @@ namespace BSHash try { - _logger.Log("Ricavando la lista dei files supportati...", LogType.INFO); ; + _logger.Log("Ricavando la lista dei files supportati...", LogType.INFO); - string[] files = Directory.GetFiles(path, "*", SearchOption.AllDirectories); + // Escludi cartelle di sistema/protette + var excludeDirs = new List { "system volume information", "$recycle.bin", "recycler", "lost+found", "found.000" }; + var files = GetAllFilesSafe(path, excludeDirs, cancellationToken); var hashSet = new HashSet(); var invalidFiles = new List(); var duplicateFiles = new List(); progressBar.Invoke((Action)(() => { - progressBar.Maximum = files.Length; + progressBar.Maximum = files.Count; progressBar.Value = 0; })); - + int processedFiles = 0; int errori = 0; int warning = 0; int inseriti = 0; int aggiornati = 0; - int totalFiles = files.Length; + int totalFiles = files.Count; _logger.Log($"Inizio controllo {totalFiles} files.", LogType.INFO); @@ -319,8 +389,6 @@ namespace BSHash hashSet.Add(hash); } - - _logger.Log("Verificando l'esistenza dell'hash...", LogType.INFO); // Controlla se l'hash esiste già nel database @@ -363,7 +431,6 @@ namespace BSHash { invalidFiles.Add(file); _logger.Log($"Errore durante la verifica del file {file}: {ex.Message}", LogType.ERROR); - errori++; } diff --git a/BSHash/BSHash/Network.cs b/BSHash/BSHash/Network.cs deleted file mode 100644 index c727a74..0000000 --- a/BSHash/BSHash/Network.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace BSHash -{ - public class Network - { - private readonly HttpClient _httpClient; - private Logger _logger; - private static readonly Random _random = new Random(); - - // Costanti per i possibili stati di risposta - public static string OK = "OK"; - public static string TIMEOUT = "TIMEOUT"; - public static string ERROR = "ERROR"; - - public Network(Logger logger) - { - _httpClient = new HttpClient(); - _logger = logger; - } - - public async Task SendDataHash(string hash) - { - try - { - /* - var content = new StringContent(data, Encoding.UTF8, "application/json"); - HttpResponseMessage response = await _httpClient.PostAsync(url, content); - - response.EnsureSuccessStatusCode(); - - string responseData = await response.Content.ReadAsStringAsync(); - return responseData; - */ - - _logger.Log("Invio dati...", LogType.INFO); - - //Simula l'attesa di una risposta con un tempo randomico - //int delay = _random.Next(1, 5000); // da 1ms a 5s - int delay = 0; // per testare il timeout - - _logger.Log("Dati inviati. Elaborazione... ", LogType.INFO); - - Thread.Sleep(delay); - - _logger.Log("Tempo di chiamata: " + delay.ToString(), LogType.INFO); - - return OK; - } - catch (Exception ex) - { - // Logga o gestisci l'eccezione come necessario - _logger.Log("Errore della chiamata: " + ex.Message, LogType.ERROR); - return $"Error: {ex.Message}"; - } - } - - public async Task GetDataHash(string hash) - { - try - { - /* - HttpResponseMessage response = await _httpClient.GetAsync(url); - - response.EnsureSuccessStatusCode(); - - string responseData = await response.Content.ReadAsStringAsync(); - return responseData; - */ - - _logger.Log("Ricezione risposta...", LogType.INFO); - - // Simula l'attesa di una risposta con un tempo randomico - //int delay = _random.Next(1, 5000); // da 1ms a 5s - int delay = 0; // per testare il timeout - - _logger.Log("Risposta ricevuta. Elaborazione... ", LogType.INFO); - - Thread.Sleep(delay); - - _logger.Log("Tempo di risposta: " + delay.ToString(), LogType.INFO); - - return OK; - } - catch (Exception ex) - { - // Logga o gestisci l'eccezione come necessario - _logger.Log("Errore della chiamata: " + ex.Message, LogType.ERROR); - return $"Error: {ex.Message}"; - } - } - } -} diff --git a/BSHash/BSHash/Program.cs b/BSHash/BSHash/Program.cs index b14750b..d621902 100644 --- a/BSHash/BSHash/Program.cs +++ b/BSHash/BSHash/Program.cs @@ -1,19 +1,34 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using System.Windows.Forms; namespace BSHash { internal static class Program { + /// + /// Punto di ingresso principale dell'applicazione HashKeeper Pro. + /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new Main()); + + // Show login form first + using (var loginForm = new LoginForm()) + { + if (loginForm.ShowDialog() == DialogResult.OK) + { + // Login successful, show main dashboard + var mainForm = new MainForm(); + Application.Run(mainForm); + } + else + { + // Login failed or cancelled, exit application + Application.Exit(); + } + } } } } diff --git a/BSHash/BSHash/Properties/Settings.Designer.cs b/BSHash/BSHash/Properties/Settings.Designer.cs index 2c00439..04de515 100644 --- a/BSHash/BSHash/Properties/Settings.Designer.cs +++ b/BSHash/BSHash/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace BSHash.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.11.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -23,6 +23,234 @@ namespace BSHash.Properties { } } + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string Password { + get { + return ((string)(this["Password"])); + } + set { + this["Password"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("localhost")] + public string DatabaseServer { + get { + return ((string)(this["DatabaseServer"])); + } + set { + this["DatabaseServer"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("HashKeeperPro")] + public string DatabaseName { + get { + return ((string)(this["DatabaseName"])); + } + set { + this["DatabaseName"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("sa")] + public string DatabaseUser { + get { + return ((string)(this["DatabaseUser"])); + } + set { + this["DatabaseUser"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string DatabasePassword { + get { + return ((string)(this["DatabasePassword"])); + } + set { + this["DatabasePassword"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("1433")] + public int DatabasePort { + get { + return ((int)(this["DatabasePort"])); + } + set { + this["DatabasePort"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("SQL Server")] + public string DatabaseProvider { + get { + return ((string)(this["DatabaseProvider"])); + } + set { + this["DatabaseProvider"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string SavedCredentials { + get { + return ((string)(this["SavedCredentials"])); + } + set { + this["SavedCredentials"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool RememberCredentials { + get { + return ((bool)(this["RememberCredentials"])); + } + set { + this["RememberCredentials"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("60")] + public int ScanIntervalMinutes { + get { + return ((int)(this["ScanIntervalMinutes"])); + } + set { + this["ScanIntervalMinutes"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("https://api.hashkeeper.com/v1/hashes")] + public string ApiEndpointUrl { + get { + return ((string)(this["ApiEndpointUrl"])); + } + set { + this["ApiEndpointUrl"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string ApiKey { + get { + return ((string)(this["ApiKey"])); + } + set { + this["ApiKey"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool EnableApiSending { + get { + return ((bool)(this["EnableApiSending"])); + } + set { + this["EnableApiSending"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("100")] + public int BatchSize { + get { + return ((int)(this["BatchSize"])); + } + set { + this["BatchSize"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool EnableDarkMode { + get { + return ((bool)(this["EnableDarkMode"])); + } + set { + this["EnableDarkMode"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool AutoSaveSettings { + get { + return ((bool)(this["AutoSaveSettings"])); + } + set { + this["AutoSaveSettings"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string DatabasePath { + get { + return ((string)(this["DatabasePath"])); + } + set { + this["DatabasePath"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool RememberUsername { + get { + return ((bool)(this["RememberUsername"])); + } + set { + this["RememberUsername"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string LastUsername { + get { + return ((string)(this["LastUsername"])); + } + set { + this["LastUsername"] = value; + } + } + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("")] @@ -47,18 +275,6 @@ namespace BSHash.Properties { } } - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("")] - public string Password { - get { - return ((string)(this["Password"])); - } - set { - this["Password"] = value; - } - } - [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("")] diff --git a/BSHash/BSHash/Properties/Settings.settings b/BSHash/BSHash/Properties/Settings.settings index d328b8d..5d09457 100644 --- a/BSHash/BSHash/Properties/Settings.settings +++ b/BSHash/BSHash/Properties/Settings.settings @@ -2,15 +2,69 @@ + + + + + localhost + + + HashKeeperPro + + + sa + + + + + + 1433 + + + SQL Server + + + + + + False + + + 60 + + + https://api.hashkeeper.com/v1/hashes + + + + + + False + + + 100 + + + False + + + True + + + + + + False + + + + - - - diff --git a/BSHash/BSHash/packages.config b/BSHash/BSHash/packages.config new file mode 100644 index 0000000..cdf4833 --- /dev/null +++ b/BSHash/BSHash/packages.config @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file