From f384995866d7f4053a3d4416ef153505787eee4a Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Thu, 18 May 2017 22:23:49 +0100 Subject: [PATCH] Added support for clamd scanning. --- osrepodbmgr.Core/ChangeLog | 12 + osrepodbmgr.Core/Context.cs | 1 + osrepodbmgr.Core/DBOps.cs | 57 ++ osrepodbmgr.Core/Settings.cs | 60 ++ osrepodbmgr.Core/Workers/Clamd.cs | 219 ++++++ osrepodbmgr.Core/Workers/Database.cs | 5 + osrepodbmgr.Core/Workers/Delegates.cs | 2 + osrepodbmgr.Core/osrepodbmgr.Core.csproj | 4 + osrepodbmgr.Core/packages.config | 1 + osrepodbmgr.Eto.Desktop/ChangeLog | 5 + osrepodbmgr.Eto.Desktop/Program.cs | 5 + osrepodbmgr.Eto.XamMac2/ChangeLog | 5 + osrepodbmgr.Eto.XamMac2/Program.cs | 5 + osrepodbmgr.Eto/ChangeLog | 8 + osrepodbmgr.Eto/dlgSettings.xeto | 159 ++-- osrepodbmgr.Eto/dlgSettings.xeto.cs | 76 ++ osrepodbmgr.Eto/frmMain.xeto | 2 +- osrepodbmgr.Eto/frmMain.xeto.cs | 71 +- osrepodbmgr/ChangeLog | 9 + osrepodbmgr/Program.cs | 5 + osrepodbmgr/dlgSettings.cs | 89 +++ osrepodbmgr/frmMain.cs | 90 ++- osrepodbmgr/gtk-gui/gui.stetic | 683 ++++++++++++------ .../gtk-gui/osrepodbmgr.dlgSettings.cs | 267 ++++++- 24 files changed, 1508 insertions(+), 332 deletions(-) create mode 100644 osrepodbmgr.Core/Workers/Clamd.cs diff --git a/osrepodbmgr.Core/ChangeLog b/osrepodbmgr.Core/ChangeLog index 08ef857..4a95ea7 100644 --- a/osrepodbmgr.Core/ChangeLog +++ b/osrepodbmgr.Core/ChangeLog @@ -1,3 +1,15 @@ +2017-05-18 Natalia Portillo + + * DBOps.cs: + * Context.cs: + * Settings.cs: + * packages.config: + * Workers/Clamd.cs: + * Workers/Database.cs: + * Workers/Delegates.cs: + * osrepodbmgr.Core.csproj: + Added support for clamd scanning. + 2017-05-18 Natalia Portillo * Workers.cs: diff --git a/osrepodbmgr.Core/Context.cs b/osrepodbmgr.Core/Context.cs index 4a255ca..073a63c 100644 --- a/osrepodbmgr.Core/Context.cs +++ b/osrepodbmgr.Core/Context.cs @@ -52,6 +52,7 @@ namespace osrepodbmgr.Core public static CICMMetadataType metadata; public static bool userExtracting; public static bool usableDotNetZip; + public static string clamdVersion; public delegate void UnarChangeStatusDelegate(); public static event UnarChangeStatusDelegate UnarChangeStatus; diff --git a/osrepodbmgr.Core/DBOps.cs b/osrepodbmgr.Core/DBOps.cs index 51eac93..9982a15 100644 --- a/osrepodbmgr.Core/DBOps.cs +++ b/osrepodbmgr.Core/DBOps.cs @@ -312,6 +312,23 @@ namespace osrepodbmgr.Core return dbcmd; } + public bool UpdateFile(DBFile file) + { + IDbCommand dbcmd = GetFileCommand(file); + IDbTransaction trans = dbCon.BeginTransaction(); + dbcmd.Transaction = trans; + + const string sql = "UPDATE files SET crack = @crack, virscan = @virscan, clamtime = @clamtime, vtotaltime = @vtotaltime, virus = @virus, length = @length " + + "WHERE sha256 = @sha256"; + + dbcmd.CommandText = sql; + + dbcmd.ExecuteNonQuery(); + trans.Commit(); + dbcmd.Dispose(); + + return true; + } public bool AddFile(DBFile file) { @@ -368,6 +385,46 @@ namespace osrepodbmgr.Core catch { return 0; } } + public DBFile GetFile(string hash) + { + string sql = string.Format("SELECT * FROM files WHERE sha256 = '{0}'", hash); + + IDbCommand dbcmd = dbCon.CreateCommand(); + IDbDataAdapter dataAdapter = dbCore.GetNewDataAdapter(); + dbcmd.CommandText = sql; + DataSet dataSet = new DataSet(); + dataAdapter.SelectCommand = dbcmd; + dataAdapter.Fill(dataSet); + DataTable dataTable = dataSet.Tables[0]; + + foreach(DataRow dRow in dataTable.Rows) + { + DBFile fEntry = new DBFile(); + + fEntry.Id = ulong.Parse(dRow["id"].ToString()); + fEntry.Sha256 = dRow["sha256"].ToString(); + fEntry.Crack = bool.Parse(dRow["crack"].ToString()); + if(dRow["virscan"] == DBNull.Value) + fEntry.HasVirus = null; + else + fEntry.HasVirus = bool.Parse(dRow["virscan"].ToString()); + if(dRow["clamtime"] == DBNull.Value) + fEntry.ClamTime = null; + else + fEntry.ClamTime = DateTime.Parse(dRow["clamtime"].ToString()); + if(dRow["vtotaltime"] == DBNull.Value) + fEntry.VirusTotalTime = null; + else + fEntry.VirusTotalTime = DateTime.Parse(dRow["vtotaltime"].ToString()); + fEntry.Virus = dRow["virus"].ToString(); + fEntry.Length = long.Parse(dRow["length"].ToString()); + + return fEntry; + } + + return null; + } + public bool GetFiles(out List entries, ulong start, ulong count) { entries = new List(); diff --git a/osrepodbmgr.Core/Settings.cs b/osrepodbmgr.Core/Settings.cs index 351b3d9..5edc8c8 100644 --- a/osrepodbmgr.Core/Settings.cs +++ b/osrepodbmgr.Core/Settings.cs @@ -40,6 +40,11 @@ namespace osrepodbmgr.Core public string RepositoryPath; public string UnArchiverPath; public AlgoEnum CompressionAlgorithm; + public bool UseAntivirus; + public bool UseClamd; + public string ClamdHost; + public ushort ClamdPort; + public bool ClamdIsLocal; } public static class Settings @@ -112,6 +117,41 @@ namespace osrepodbmgr.Core else Current.CompressionAlgorithm = AlgoEnum.GZip; + if(parsedPreferences.TryGetValue("UseAntivirus", out obj)) + { + Current.UseAntivirus = ((NSNumber)obj).ToBool(); + } + else + Current.UseAntivirus = false; + + if(parsedPreferences.TryGetValue("UseClamd", out obj)) + { + Current.UseClamd = ((NSNumber)obj).ToBool(); + } + else + Current.UseClamd = false; + + if(parsedPreferences.TryGetValue("ClamdHost", out obj)) + { + Current.ClamdHost = ((NSString)obj).ToString(); + } + else + Current.ClamdHost = null; + + if(parsedPreferences.TryGetValue("ClamdPort", out obj)) + { + Current.ClamdPort = (ushort)((NSNumber)obj).ToLong(); + } + else + Current.ClamdPort = 3310; + + if(parsedPreferences.TryGetValue("ClamdIsLocal", out obj)) + { + Current.ClamdIsLocal = ((NSNumber)obj).ToBool(); + } + else + Current.ClamdIsLocal = false; + prefsFs.Close(); } else { @@ -150,6 +190,11 @@ namespace osrepodbmgr.Core Current.UnArchiverPath = (string)key.GetValue("UnArchiverPath"); if(!Enum.TryParse((string)key.GetValue("CompressionAlgorithm"), true, out Current.CompressionAlgorithm)) Current.CompressionAlgorithm = AlgoEnum.GZip; + Current.UseAntivirus = (bool)key.GetValue("UseAntivirus"); + Current.UseClamd = (bool)key.GetValue("UseClamd"); + Current.ClamdHost = (string)key.GetValue("ClamdHost"); + Current.ClamdPort = (ushort)key.GetValue("ClamdPort"); + Current.ClamdIsLocal = (bool)key.GetValue("ClamdIsLocal"); } break; default: @@ -201,6 +246,11 @@ namespace osrepodbmgr.Core root.Add("RepositoryPath", Current.RepositoryPath); root.Add("UnArchiverPath", Current.UnArchiverPath); root.Add("CompressionAlgorithm", Current.CompressionAlgorithm.ToString()); + root.Add("UseAntivirus", Current.UseAntivirus); + root.Add("UseClamd", Current.UseClamd); + root.Add("ClamdHost", Current.ClamdHost); + root.Add("ClamdPort", Current.ClamdPort); + root.Add("ClamdIsLocal", Current.ClamdIsLocal); string preferencesPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Preferences"); string preferencesFilePath = Path.Combine(preferencesPath, "com.claunia.museum.osrepodbmgr.plist"); @@ -225,6 +275,11 @@ namespace osrepodbmgr.Core if (Current.UnArchiverPath != null) key.SetValue("UnArchiverPath", Current.UnArchiverPath); key.SetValue("CompressionAlgorithm", Current.CompressionAlgorithm); + key.SetValue("UseAntivirus", Current.UseAntivirus); + key.SetValue("UseClamd", Current.UseClamd); + key.SetValue("ClamdHost", Current.ClamdHost); + key.SetValue("ClamdPort", Current.ClamdPort); + key.SetValue("ClamdIsLocal", Current.ClamdIsLocal); } break; default: @@ -260,6 +315,11 @@ namespace osrepodbmgr.Core Current.RepositoryPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "osrepo"); Current.UnArchiverPath = null; Current.CompressionAlgorithm = AlgoEnum.GZip; + Current.UseAntivirus = false; + Current.UseClamd = false; + Current.ClamdHost = null; + Current.ClamdPort = 3310; + Current.ClamdIsLocal = false; } } } diff --git a/osrepodbmgr.Core/Workers/Clamd.cs b/osrepodbmgr.Core/Workers/Clamd.cs new file mode 100644 index 0000000..458f740 --- /dev/null +++ b/osrepodbmgr.Core/Workers/Clamd.cs @@ -0,0 +1,219 @@ +// +// Author: +// Natalia Portillo claunia@claunia.com +// +// Copyright (c) 2017, © Claunia.com +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the distribution. +// * Neither the name of the [ORGANIZATION] nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +using System; +using nClam; +using System.Threading.Tasks; +using System.IO; +using SharpCompress.Compressors.LZMA; +using SharpCompress.Compressors.Deflate; +using SharpCompress.Compressors.BZip2; +using System.Threading; + +namespace osrepodbmgr.Core +{ + public static partial class Workers + { + static ClamClient clam; + + public static void InitClamd() + { + if(!Settings.Current.UseClamd || !Settings.Current.UseAntivirus) + { + Context.clamdVersion = null; + return; + } + + TestClamd(); + } + + public static void TestClamd() + { + Task.Run(async () => + { + try + { + clam = new ClamClient(Settings.Current.ClamdHost, Settings.Current.ClamdPort); + Context.clamdVersion = await clam.GetVersionAsync(); + } + catch(System.Net.Sockets.SocketException) + { + + } + }).Wait(); + } + + public static void ClamScanFileFromRepo(DBFile file) + { + try + { + if(Context.clamdVersion == null) + { + if(Failed != null) + Failed("clamd is not usable"); + return; + } + + if(clam == null) + { + if(Failed != null) + Failed("clamd is not initalized"); + } + + string repoPath; + AlgoEnum algorithm; + + if(File.Exists(Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(), + file.Sha256[1].ToString(), file.Sha256[2].ToString(), + file.Sha256[3].ToString(), file.Sha256[4].ToString(), + file.Sha256 + ".gz"))) + { + repoPath = Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(), + file.Sha256[1].ToString(), file.Sha256[2].ToString(), + file.Sha256[3].ToString(), file.Sha256[4].ToString(), + file.Sha256 + ".gz"); + algorithm = AlgoEnum.GZip; + } + else if(File.Exists(Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(), + file.Sha256[1].ToString(), file.Sha256[2].ToString(), + file.Sha256[3].ToString(), file.Sha256[4].ToString(), + file.Sha256 + ".bz2"))) + { + repoPath = Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(), + file.Sha256[1].ToString(), file.Sha256[2].ToString(), + file.Sha256[3].ToString(), file.Sha256[4].ToString(), + file.Sha256 + ".bz2"); + algorithm = AlgoEnum.BZip2; + } + else if(File.Exists(Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(), + file.Sha256[1].ToString(), file.Sha256[2].ToString(), + file.Sha256[3].ToString(), file.Sha256[4].ToString(), + file.Sha256 + ".lzma"))) + { + repoPath = Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(), + file.Sha256[1].ToString(), file.Sha256[2].ToString(), + file.Sha256[3].ToString(), file.Sha256[4].ToString(), + file.Sha256 + ".lzma"); + algorithm = AlgoEnum.LZMA; + } + else + { + if(Failed != null) + Failed(string.Format("Cannot find file with hash {0} in the repository", file.Sha256)); + return; + } + + ClamScanResult result = null; + Stream zStream = null; + + if(Settings.Current.ClamdIsLocal) + { + // clamd supports gzip and bzip2 but not lzma + if(algorithm == AlgoEnum.LZMA) + { + string tmpFile = Path.Combine(Settings.Current.TemporaryFolder, Path.GetTempFileName()); + FileStream outFs = new FileStream(tmpFile, FileMode.Create, FileAccess.Write); + FileStream inFs = new FileStream(repoPath, FileMode.Open, FileAccess.Read); + + byte[] properties = new byte[5]; + inFs.Read(properties, 0, 5); + inFs.Seek(8, SeekOrigin.Current); + zStream = new LzmaStream(properties, inFs); + + zStream.CopyTo(outFs); + zStream.Close(); + outFs.Close(); + + Task.Run(async () => + { + result = await clam.ScanFileOnServerMultithreadedAsync(tmpFile); + }).Wait(); + + File.Delete(tmpFile); + } + else + Task.Run(async () => + { + result = await clam.ScanFileOnServerMultithreadedAsync(repoPath); + }).Wait(); + } + else + { + FileStream inFs = new FileStream(repoPath, FileMode.Open, FileAccess.Read); + + switch(algorithm) + { + case AlgoEnum.GZip: + zStream = new GZipStream(inFs, SharpCompress.Compressors.CompressionMode.Decompress); + break; + case AlgoEnum.BZip2: + zStream = new BZip2Stream(inFs, SharpCompress.Compressors.CompressionMode.Decompress); + break; + case AlgoEnum.LZMA: + byte[] properties = new byte[5]; + inFs.Read(properties, 0, 5); + inFs.Seek(8, SeekOrigin.Current); + zStream = new LzmaStream(properties, inFs); + break; + } + + Task.Run(async () => + { + result = await clam.SendAndScanFileAsync(zStream); + }).Wait(); + zStream.Close(); + } + + if(result.InfectedFiles != null && result.InfectedFiles.Count > 0) + { + file.HasVirus = true; + file.Virus = result.InfectedFiles[0].VirusName; + } + else if(file.HasVirus == null) + { + // If no scan has been done, mark as false. + // If a positive has already existed don't overwrite it. + file.HasVirus = false; + file.Virus = null; + } + file.ClamTime = DateTime.UtcNow; + + dbCore.DBOps.UpdateFile(file); + + if(ScanFinished != null) + ScanFinished(file); + + return; + } + catch(Exception ex) + { + if(Failed != null) + Failed(string.Format("Exception {0} when calling clamd", ex.Message)); + } + } + } +} diff --git a/osrepodbmgr.Core/Workers/Database.cs b/osrepodbmgr.Core/Workers/Database.cs index 609c10e..fb9b44d 100644 --- a/osrepodbmgr.Core/Workers/Database.cs +++ b/osrepodbmgr.Core/Workers/Database.cs @@ -349,5 +349,10 @@ namespace osrepodbmgr.Core Failed(string.Format("Exception {0}\n{1}", ex.Message, ex.InnerException)); } } + + public static DBFile GetDBFile(string hash) + { + return dbCore.DBOps.GetFile(hash); + } } } diff --git a/osrepodbmgr.Core/Workers/Delegates.cs b/osrepodbmgr.Core/Workers/Delegates.cs index 9f05964..0c88139 100644 --- a/osrepodbmgr.Core/Workers/Delegates.cs +++ b/osrepodbmgr.Core/Workers/Delegates.cs @@ -41,6 +41,7 @@ namespace osrepodbmgr.Core public delegate void AddOSDelegate(DBEntry os, bool existsInRepo, string pathInRepo); public delegate void AddFileDelegate(DBFile file); public delegate void AddFilesDelegate(List file); + public delegate void ScanFinishedDelegate(DBFile file); public static event UpdateProgressDelegate UpdateProgress; public static event UpdateProgress2Delegate UpdateProgress2; @@ -51,5 +52,6 @@ namespace osrepodbmgr.Core public static event AddOSDelegate AddOS; public static event AddFileDelegate AddFile; public static event AddFilesDelegate AddFiles; + public static event ScanFinishedDelegate ScanFinished; } } diff --git a/osrepodbmgr.Core/osrepodbmgr.Core.csproj b/osrepodbmgr.Core/osrepodbmgr.Core.csproj index ac9af8c..d4daa17 100644 --- a/osrepodbmgr.Core/osrepodbmgr.Core.csproj +++ b/osrepodbmgr.Core/osrepodbmgr.Core.csproj @@ -44,6 +44,9 @@ ..\packages\SharpCompress.0.15.2\lib\net45\SharpCompress.dll + + ..\packages\nClam.3.0.0\lib\net45\nClam.dll + @@ -66,6 +69,7 @@ + diff --git a/osrepodbmgr.Core/packages.config b/osrepodbmgr.Core/packages.config index 7269f07..70132e7 100644 --- a/osrepodbmgr.Core/packages.config +++ b/osrepodbmgr.Core/packages.config @@ -1,6 +1,7 @@  + diff --git a/osrepodbmgr.Eto.Desktop/ChangeLog b/osrepodbmgr.Eto.Desktop/ChangeLog index 20af705..9c872a4 100644 --- a/osrepodbmgr.Eto.Desktop/ChangeLog +++ b/osrepodbmgr.Eto.Desktop/ChangeLog @@ -1,3 +1,8 @@ +2017-05-18 Natalia Portillo + + * Program.cs: + Added support for clamd scanning. + 2017-05-18 Natalia Portillo * osrepodbmgr.Eto.Desktop.csproj: diff --git a/osrepodbmgr.Eto.Desktop/Program.cs b/osrepodbmgr.Eto.Desktop/Program.cs index b91ece8..33ddb58 100644 --- a/osrepodbmgr.Eto.Desktop/Program.cs +++ b/osrepodbmgr.Eto.Desktop/Program.cs @@ -39,6 +39,11 @@ namespace osrepodbmgr.Eto.Desktop { Settings.LoadSettings(); Context.CheckUnar(); + if(Core.Settings.Current.UseAntivirus) + { + if(Core.Settings.Current.UseClamd) + Workers.InitClamd(); + } Context.usableDotNetZip = !Platform.Detect.IsMac && !Platform.Detect.IsIos; new Application(Platform.Detect).Run(new frmMain()); diff --git a/osrepodbmgr.Eto.XamMac2/ChangeLog b/osrepodbmgr.Eto.XamMac2/ChangeLog index 14f7172..ac892d4 100644 --- a/osrepodbmgr.Eto.XamMac2/ChangeLog +++ b/osrepodbmgr.Eto.XamMac2/ChangeLog @@ -1,3 +1,8 @@ +2017-05-18 Natalia Portillo + + * Program.cs: + Added support for clamd scanning. + 2017-05-18 Natalia Portillo * osrepodbmgr.Eto.XamMac2.csproj: diff --git a/osrepodbmgr.Eto.XamMac2/Program.cs b/osrepodbmgr.Eto.XamMac2/Program.cs index a62b0c8..5017970 100644 --- a/osrepodbmgr.Eto.XamMac2/Program.cs +++ b/osrepodbmgr.Eto.XamMac2/Program.cs @@ -39,6 +39,11 @@ namespace osrepodbmgr.Eto.XamMac2 { Settings.LoadSettings(); Context.CheckUnar(); + if(Core.Settings.Current.UseAntivirus) + { + if(Core.Settings.Current.UseClamd) + Workers.InitClamd(); + } Context.usableDotNetZip = false; new Application(Platforms.XamMac2).Run(new frmMain()); } diff --git a/osrepodbmgr.Eto/ChangeLog b/osrepodbmgr.Eto/ChangeLog index 50ffb99..3b9bd5a 100644 --- a/osrepodbmgr.Eto/ChangeLog +++ b/osrepodbmgr.Eto/ChangeLog @@ -1,3 +1,11 @@ +2017-05-18 Natalia Portillo + + * frmMain.xeto: + * frmMain.xeto.cs: + * dlgSettings.xeto: + * dlgSettings.xeto.cs: + Added support for clamd scanning. + 2017-05-18 Natalia Portillo * dlgAdd.xeto: diff --git a/osrepodbmgr.Eto/dlgSettings.xeto b/osrepodbmgr.Eto/dlgSettings.xeto index bf57394..0feb2c9 100644 --- a/osrepodbmgr.Eto/dlgSettings.xeto +++ b/osrepodbmgr.Eto/dlgSettings.xeto @@ -1,68 +1,109 @@  - + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Use antivirus? + + + + Use clamd? + + + + + + + + + + + + + + + + + + + + + + + + Clamd is local? + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/osrepodbmgr.Eto/dlgSettings.xeto.cs b/osrepodbmgr.Eto/dlgSettings.xeto.cs index 1bf4741..3d54f98 100644 --- a/osrepodbmgr.Eto/dlgSettings.xeto.cs +++ b/osrepodbmgr.Eto/dlgSettings.xeto.cs @@ -45,6 +45,14 @@ namespace osrepodbmgr.Eto Label lblUnarVersion; EnumDropDown cmbCompAlg; StackLayout StackLayoutForAlgoEnum; + GroupBox frmClamd; + CheckBox chkAntivirus; + CheckBox chkClamd; + TextBox txtClamdHost; + NumericUpDown spClamdPort; + Button btnClamdTest; + Label lblClamdVersion; + CheckBox chkClamdIsLocal; #pragma warning restore 0649 #endregion XAML UI elements @@ -64,6 +72,17 @@ namespace osrepodbmgr.Eto cmbCompAlg = new EnumDropDown(); StackLayoutForAlgoEnum.Items.Add(new StackLayoutItem(cmbCompAlg, HorizontalAlignment.Stretch, true)); cmbCompAlg.SelectedValue = Settings.Current.CompressionAlgorithm; + + spClamdPort.Value = 3310; + chkAntivirus.Checked = Core.Settings.Current.UseAntivirus; + frmClamd.Visible = chkAntivirus.Checked.Value; + if(Core.Settings.Current.UseAntivirus && Core.Settings.Current.UseClamd) + { + chkClamd.Checked = Core.Settings.Current.UseClamd; + txtClamdHost.Text = Core.Settings.Current.ClamdHost; + spClamdPort.Value = Core.Settings.Current.ClamdPort; + chkClamdIsLocal.Checked = Core.Settings.Current.ClamdIsLocal; + } } protected void OnBtnCancelClicked(object sender, EventArgs e) @@ -79,9 +98,18 @@ namespace osrepodbmgr.Eto Settings.Current.DatabasePath = txtDatabase.Text; Settings.Current.RepositoryPath = txtRepository.Text; Settings.Current.CompressionAlgorithm = cmbCompAlg.SelectedValue; + if(!chkClamd.Checked.Value || !chkAntivirus.Checked.Value) + { + Core.Settings.Current.UseClamd = false; + Core.Settings.Current.ClamdHost = null; + Core.Settings.Current.ClamdPort = 3310; + Core.Settings.Current.ClamdIsLocal = false; + } Settings.SaveSettings(); Workers.CloseDB(); Workers.InitDB(); + Context.clamdVersion = null; + Core.Workers.InitClamd(); Context.CheckUnar(); Close(); } @@ -218,5 +246,53 @@ namespace osrepodbmgr.Eto MessageBox.Show(text, MessageBoxType.Error); }); } + + protected void OnChkAntivirusToggled(object sender, EventArgs e) + { + frmClamd.Visible = chkAntivirus.Checked.Value; + } + + protected void OnChkClamdToggled(object sender, EventArgs e) + { + txtClamdHost.Enabled = chkClamd.Checked.Value; + spClamdPort.Enabled = chkClamd.Checked.Value; + btnClamdTest.Enabled = chkClamd.Checked.Value; + lblClamdVersion.Visible = false; + chkClamdIsLocal.Enabled = chkClamd.Checked.Value; + } + + protected void OnBtnClamdTestClicked(object sender, EventArgs e) + { + lblClamdVersion.Visible = false; + + if(string.IsNullOrEmpty(txtClamdHost.Text)) + { + MessageBox.Show("clamd host cannot be empty", MessageBoxType.Error); + return; + } + + string oldVersion = Context.clamdVersion; + Context.clamdVersion = null; + + string oldHost = Core.Settings.Current.ClamdHost; + ushort oldPort = Core.Settings.Current.ClamdPort; + Core.Settings.Current.ClamdHost = txtClamdHost.Text; + Core.Settings.Current.ClamdPort = (ushort)spClamdPort.Value; + + Workers.TestClamd(); + + Core.Settings.Current.ClamdHost = oldHost; + Core.Settings.Current.ClamdPort = oldPort; + + if(string.IsNullOrEmpty(Context.clamdVersion)) + { + MessageBox.Show("Cannot connect to clamd", MessageBoxType.Error); + return; + } + + lblClamdVersion.Text = Context.clamdVersion; + Context.clamdVersion = oldVersion; + lblClamdVersion.Visible = true; + } } } diff --git a/osrepodbmgr.Eto/frmMain.xeto b/osrepodbmgr.Eto/frmMain.xeto index 7db6631..1106789 100644 --- a/osrepodbmgr.Eto/frmMain.xeto +++ b/osrepodbmgr.Eto/frmMain.xeto @@ -32,7 +32,7 @@ - + diff --git a/osrepodbmgr.Eto/frmMain.xeto.cs b/osrepodbmgr.Eto/frmMain.xeto.cs index 7c6355a..ae66b1c 100644 --- a/osrepodbmgr.Eto/frmMain.xeto.cs +++ b/osrepodbmgr.Eto/frmMain.xeto.cs @@ -43,6 +43,8 @@ namespace osrepodbmgr.Eto Thread thdSaveAs; Thread thdPopulateFiles; bool populatingFiles; + Thread thdScanFile; + DBFile outIter; #region XAML UI elements #pragma warning disable 0649 @@ -637,6 +639,74 @@ namespace osrepodbmgr.Eto protected void OnBtnScanWithClamdClicked(object sender, EventArgs e) { + if(treeFiles.SelectedItem != null) + { + DBFile file = Workers.GetDBFile(((DBFile)treeFiles.SelectedItem).Sha256); + outIter = (osrepodbmgr.Core.DBFile)treeFiles.SelectedItem; + + if(file == null) + { + MessageBox.Show("Cannot get file from database", MessageBoxType.Error); + return; + } + + treeFiles.Enabled = false; + btnToggleCrack.Enabled = false; + btnScanWithClamd.Enabled = false; + btnCheckInVirusTotal.Enabled = false; + prgProgress.Visible = true; + lblProgress.Visible = true; + Workers.Failed += ClamdFailed; + Workers.ScanFinished += ClamdFinished; + + lblProgress.Text = "Scanning file with clamd."; + prgProgress.Indeterminate = true; + + thdScanFile = new Thread(() => Workers.ClamScanFileFromRepo(file)); + thdScanFile.Start(); + } + } + + void ClamdFailed(string text) + { + Application.Instance.Invoke(delegate + { + treeFiles.Enabled = true; + btnToggleCrack.Enabled = true; + btnScanWithClamd.Enabled = true; + btnCheckInVirusTotal.Enabled = true; + prgProgress.Visible = false; + lblProgress.Visible = false; + Workers.Failed -= ClamdFailed; + Workers.ScanFinished -= ClamdFinished; + lblProgress.Text = ""; + if(thdScanFile != null) + { + thdScanFile.Abort(); + thdScanFile = null; + } + }); + } + + void ClamdFinished(DBFile file) + { + Application.Instance.Invoke(delegate + { + treeFiles.Enabled = true; + btnToggleCrack.Enabled = true; + btnScanWithClamd.Enabled = true; + btnCheckInVirusTotal.Enabled = true; + Workers.Failed -= ClamdFailed; + Workers.ScanFinished -= ClamdFinished; + lblProgress.Text = ""; + prgProgress.Visible = false; + lblProgress.Visible = false; + if(thdScanFile != null) + thdScanFile = null; + + lstFiles.Remove(outIter); + AddFile(file); + }); } protected void OnBtnCheckInVirusTotalClicked(object sender, EventArgs e) @@ -646,7 +716,6 @@ namespace osrepodbmgr.Eto protected void OnBtnPopulateFilesClicked(object sender, EventArgs e) { // TODO: Implement - btnScanWithClamd.Enabled = false; btnCheckInVirusTotal.Enabled = false; tabOSes.Enabled = false; diff --git a/osrepodbmgr/ChangeLog b/osrepodbmgr/ChangeLog index 21ea782..817f2c6 100644 --- a/osrepodbmgr/ChangeLog +++ b/osrepodbmgr/ChangeLog @@ -1,3 +1,12 @@ +2017-05-18 Natalia Portillo + + * frmMain.cs: + * Program.cs: + * dlgSettings.cs: + * gtk-gui/gui.stetic: + * gtk-gui/osrepodbmgr.dlgSettings.cs: + Added support for clamd scanning. + 2017-05-18 Natalia Portillo * dlgAdd.cs: diff --git a/osrepodbmgr/Program.cs b/osrepodbmgr/Program.cs index ba39894..fb521bd 100644 --- a/osrepodbmgr/Program.cs +++ b/osrepodbmgr/Program.cs @@ -37,6 +37,11 @@ namespace osrepodbmgr Core.Settings.LoadSettings(); Context.CheckUnar(); Context.usableDotNetZip = true; + if(Core.Settings.Current.UseAntivirus) + { + if(Core.Settings.Current.UseClamd) + Workers.InitClamd(); + } Application.Init(); frmMain win = new frmMain(); win.Show(); diff --git a/osrepodbmgr/dlgSettings.cs b/osrepodbmgr/dlgSettings.cs index 3e47c95..7e288b8 100644 --- a/osrepodbmgr/dlgSettings.cs +++ b/osrepodbmgr/dlgSettings.cs @@ -71,6 +71,17 @@ namespace osrepodbmgr } } while(cmbCompAlg.Model.IterNext(ref iter)); + + spClamdPort.Value = 3310; + chkAntivirus.Active = Core.Settings.Current.UseAntivirus; + frmClamd.Visible = chkAntivirus.Active; + if(Core.Settings.Current.UseAntivirus && Core.Settings.Current.UseClamd) + { + chkClamd.Active = Core.Settings.Current.UseClamd; + txtClamdHost.Text = Core.Settings.Current.ClamdHost; + spClamdPort.Value = Core.Settings.Current.ClamdPort; + chkClamdIsLocal.Active = Core.Settings.Current.ClamdIsLocal; + } } protected void OnBtnCancelClicked(object sender, EventArgs e) @@ -80,15 +91,41 @@ namespace osrepodbmgr protected void OnBtnApplyClicked(object sender, EventArgs e) { + if(chkAntivirus.Active && chkClamd.Active) + { + if(string.IsNullOrEmpty(txtClamdHost.Text)) + { + MessageDialog dlgMsg = new MessageDialog(this, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, "clamd host cannot be empty"); + dlgMsg.Run(); + dlgMsg.Destroy(); + return; + } + + } + // TODO: Check sanity Core.Settings.Current.TemporaryFolder = txtTmp.Text; Core.Settings.Current.UnArchiverPath = txtUnar.Text; Core.Settings.Current.DatabasePath = txtDatabase.Text; Core.Settings.Current.RepositoryPath = txtRepository.Text; + Core.Settings.Current.UseAntivirus = chkAntivirus.Active; + Core.Settings.Current.UseClamd = chkClamd.Active; + Core.Settings.Current.ClamdHost = txtClamdHost.Text; + Core.Settings.Current.ClamdPort = (ushort)spClamdPort.Value; + Core.Settings.Current.ClamdIsLocal = chkClamdIsLocal.Active; Core.Settings.Current.CompressionAlgorithm = (AlgoEnum)Enum.Parse(typeof(AlgoEnum), cmbCompAlg.ActiveText); + if(!chkClamd.Active || !chkAntivirus.Active) + { + Core.Settings.Current.UseClamd = false; + Core.Settings.Current.ClamdHost = null; + Core.Settings.Current.ClamdPort = 3310; + Core.Settings.Current.ClamdIsLocal = false; + } Core.Settings.SaveSettings(); Core.Workers.CloseDB(); Core.Workers.InitDB(); + Context.clamdVersion = null; + Core.Workers.InitClamd(); Context.CheckUnar(); btnDialog.Click(); } @@ -245,5 +282,57 @@ namespace osrepodbmgr dlgMsg.Destroy(); }); } + + protected void OnChkAntivirusToggled(object sender, EventArgs e) + { + frmClamd.Visible = chkAntivirus.Active; + } + + protected void OnChkClamdToggled(object sender, EventArgs e) + { + txtClamdHost.Sensitive = chkClamd.Active; + spClamdPort.Sensitive = chkClamd.Active; + btnClamdTest.Sensitive = chkClamd.Active; + lblClamdVersion.Visible = false; + chkClamdIsLocal.Sensitive = chkClamd.Active; + } + + protected void OnBtnClamdTestClicked(object sender, EventArgs e) + { + lblClamdVersion.Visible = false; + + if(string.IsNullOrEmpty(txtClamdHost.Text)) + { + MessageDialog dlgMsg = new MessageDialog(this, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, "clamd host cannot be empty"); + dlgMsg.Run(); + dlgMsg.Destroy(); + return; + } + + string oldVersion = Context.clamdVersion; + Context.clamdVersion = null; + + string oldHost = Core.Settings.Current.ClamdHost; + ushort oldPort = Core.Settings.Current.ClamdPort; + Core.Settings.Current.ClamdHost = txtClamdHost.Text; + Core.Settings.Current.ClamdPort = (ushort)spClamdPort.Value; + + Workers.TestClamd(); + + Core.Settings.Current.ClamdHost = oldHost; + Core.Settings.Current.ClamdPort = oldPort; + + if(string.IsNullOrEmpty(Context.clamdVersion)) + { + MessageDialog dlgMsg = new MessageDialog(this, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, "Cannot connect to clamd"); + dlgMsg.Run(); + dlgMsg.Destroy(); + return; + } + + lblClamdVersion.Text = Context.clamdVersion; + Context.clamdVersion = oldVersion; + lblClamdVersion.Visible = true; + } } } diff --git a/osrepodbmgr/frmMain.cs b/osrepodbmgr/frmMain.cs index e448391..3566028 100644 --- a/osrepodbmgr/frmMain.cs +++ b/osrepodbmgr/frmMain.cs @@ -44,6 +44,8 @@ namespace osrepodbmgr Thread thdSaveAs; Thread thdPopulateFiles; bool populatingFiles; + Thread thdScanFile; + TreeIter outIter; public frmMain() : base(WindowType.Toplevel) @@ -652,6 +654,93 @@ namespace osrepodbmgr protected void OnBtnScanWithClamdClicked(object sender, EventArgs e) { + if(treeFiles.Selection.GetSelected(out outIter)) + { + DBFile file = Workers.GetDBFile((string)fileView.GetValue(outIter, 0)); + + if(file == null) + { + MessageDialog dlgMsg = new MessageDialog(this, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, + "Cannot get file from database"); + dlgMsg.Run(); + dlgMsg.Destroy(); + return; + } + + treeFiles.Sensitive = false; + btnToggleCrack.Sensitive = false; + btnScanWithClamd.Sensitive = false; + btnCheckInVirusTotal.Sensitive = false; + prgProgress.Visible = true; + Workers.Failed += ClamdFailed; + Workers.ScanFinished += ClamdFinished; + + prgProgress.Text = "Scanning file with clamd."; + thdPulseProgress = new Thread(() => + { + while(true) + { + Application.Invoke(delegate + { + prgProgress.Pulse(); + }); + Thread.Sleep(66); + } + }); + + thdScanFile = new Thread(() => Workers.ClamScanFileFromRepo(file)); + thdScanFile.Start(); + } + } + + void ClamdFailed(string text) + { + Application.Invoke(delegate + { + treeFiles.Sensitive = true; + btnToggleCrack.Sensitive = true; + btnScanWithClamd.Sensitive = true; + btnCheckInVirusTotal.Sensitive = true; + prgProgress.Visible = false; + Workers.Failed -= ClamdFailed; + Workers.ScanFinished -= ClamdFinished; + prgProgress.Text = ""; + if(thdPulseProgress != null) + { + thdPulseProgress.Abort(); + thdPulseProgress = null; + } + if(thdScanFile != null) + { + thdScanFile.Abort(); + thdScanFile = null; + } + }); + } + + void ClamdFinished(DBFile file) + { + Application.Invoke(delegate + { + treeFiles.Sensitive = true; + btnToggleCrack.Sensitive = true; + btnScanWithClamd.Sensitive = true; + btnCheckInVirusTotal.Sensitive = true; + Workers.Failed -= ClamdFailed; + Workers.ScanFinished -= ClamdFinished; + prgProgress.Text = ""; + prgProgress.Visible = false; + if(thdPulseProgress != null) + { + thdPulseProgress.Abort(); + thdPulseProgress = null; + } + if(thdScanFile != null) + thdScanFile = null; + + fileView.Remove(ref outIter); + AddFile(file); + }); } protected void OnBtnCheckInVirusTotalClicked(object sender, EventArgs e) @@ -661,7 +750,6 @@ namespace osrepodbmgr protected void OnBtnPopulateFilesClicked(object sender, EventArgs e) { // TODO: Implement - btnScanWithClamd.Sensitive = false; btnCheckInVirusTotal.Sensitive = false; notebook1.GetNthPage(0).Sensitive = false; diff --git a/osrepodbmgr/gtk-gui/gui.stetic b/osrepodbmgr/gtk-gui/gui.stetic index 5cda259..4e7a699 100644 --- a/osrepodbmgr/gtk-gui/gui.stetic +++ b/osrepodbmgr/gtk-gui/gui.stetic @@ -967,7 +967,7 @@ QNX/QNX/20090229/source.zip - + Settings CenterOnParent @@ -978,13 +978,275 @@ QNX/QNX/20090229/source.zip 6 - + 6 - + - Database file + 6 + + + + 6 + + + + Database file + + + 0 + True + False + False + + + + + + True + True + + + + 1 + True + + + + + + True + TextAndIcon + stock:gtk-open Menu + Choose + True + + + + 2 + True + False + False + + + + + 0 + True + False + False + + + + + + 6 + + + + Repository folder + + + 0 + True + False + False + + + + + + True + True + + + + 1 + True + + + + + + True + TextAndIcon + stock:gtk-open Menu + Choose + True + + + + 2 + True + False + False + + + + + 1 + True + False + False + + + + + + 6 + + + + Temporary folder + + + 0 + True + False + False + + + + + + True + True + + + + 1 + True + + + + + + True + TextAndIcon + stock:gtk-open Menu + Choose + True + + + + 2 + True + False + False + + + + + 2 + True + False + False + + + + + + 6 + + + + Path to unar + + + 0 + True + False + False + + + + + + True + True + + + + 1 + True + + + + + + True + TextAndIcon + stock:gtk-open Menu + Choose + True + + + + 2 + True + False + False + + + + + 3 + True + False + False + + + + + + False + label1 + + + 4 + True + False + False + + + + + + 6 + + + + Compression algorithm + + + 0 + True + False + False + + + + + + True + + + + 1 + True + False + False + + + + + 5 + True + False + False + + 0 @@ -994,30 +1256,194 @@ QNX/QNX/20090229/source.zip - + - True - True - + 6 + + + + True + Use antivirus? + True + True + True + + + + 0 + True + False + False + + + + + + None + + + + 0 + 0 + 12 + + + + 6 + + + + True + Use clamd? + True + True + True + + + + 0 + True + False + False + + + + + + 6 + + + + Host + + + 0 + True + False + False + + + + + + True + True + + + + 1 + True + + + + + + port + + + 2 + True + False + False + + + + + + True + 1 + 65535 + 10 + 1 + 1 + True + 3310 + + + 3 + True + False + False + + + + + + True + TextOnly + Test + True + + + + 4 + True + False + False + + + + + 1 + True + False + False + + + + + + label4 + + + 2 + True + False + False + + + + + + True + Clamd is local? + True + True + True + + + 3 + True + False + False + + + + + + + + + + <b>clamd</b> + True + + + label_item + + + + + 1 + True + False + False + + 1 True - - - - - - True - TextAndIcon - stock:gtk-open Menu - Choose - True - - - - 2 - True False False @@ -1030,215 +1456,6 @@ QNX/QNX/20090229/source.zip False - - - - 6 - - - - Repository folder - - - 0 - True - False - False - - - - - - True - True - - - - 1 - True - - - - - - True - TextAndIcon - stock:gtk-open Menu - Choose - True - - - - 2 - True - False - False - - - - - 1 - True - False - False - - - - - - 6 - - - - Temporary folder - - - 0 - True - False - False - - - - - - True - True - - - - 1 - True - - - - - - True - TextAndIcon - stock:gtk-open Menu - Choose - True - - - - 2 - True - False - False - - - - - 2 - True - False - False - - - - - - 6 - - - - Path to unar - - - 0 - True - False - False - - - - - - True - True - - - - 1 - True - - - - - - True - TextAndIcon - stock:gtk-open Menu - Choose - True - - - - 2 - True - False - False - - - - - 3 - True - False - False - - - - - - False - label1 - - - 4 - True - False - False - - - - - - 6 - - - - Compression algorithm - - - 0 - True - False - False - - - - - - True - - - - 1 - True - False - False - - - - - 5 - True - False - False - - @@ -1280,7 +1497,7 @@ QNX/QNX/20090229/source.zip - 6 + 1 True False False diff --git a/osrepodbmgr/gtk-gui/osrepodbmgr.dlgSettings.cs b/osrepodbmgr/gtk-gui/osrepodbmgr.dlgSettings.cs index ffc411c..a22a14e 100644 --- a/osrepodbmgr/gtk-gui/osrepodbmgr.dlgSettings.cs +++ b/osrepodbmgr/gtk-gui/osrepodbmgr.dlgSettings.cs @@ -4,6 +4,10 @@ namespace osrepodbmgr { public partial class dlgSettings { + private global::Gtk.HBox hbox2; + + private global::Gtk.VBox vbox3; + private global::Gtk.HBox hbox26; private global::Gtk.Label lblDatabase; @@ -44,6 +48,36 @@ namespace osrepodbmgr private global::Gtk.ComboBox cmbCompAlg; + private global::Gtk.VBox vbox4; + + private global::Gtk.CheckButton chkAntivirus; + + private global::Gtk.Frame frmClamd; + + private global::Gtk.Alignment GtkAlignment6; + + private global::Gtk.VBox vbox6; + + private global::Gtk.CheckButton chkClamd; + + private global::Gtk.HBox hbox3; + + private global::Gtk.Label lblClamdHost; + + private global::Gtk.Entry txtClamdHost; + + private global::Gtk.Label lblClamdPort; + + private global::Gtk.SpinButton spClamdPort; + + private global::Gtk.Button btnClamdTest; + + private global::Gtk.Label lblClamdVersion; + + private global::Gtk.CheckButton chkClamdIsLocal; + + private global::Gtk.Label GtkLabel7; + private global::Gtk.HBox hbox18; private global::Gtk.Button btnCancel; @@ -64,6 +98,14 @@ namespace osrepodbmgr w1.Name = "vbox5"; w1.Spacing = 6; // Container child vbox5.Gtk.Box+BoxChild + this.hbox2 = new global::Gtk.HBox(); + this.hbox2.Name = "hbox2"; + this.hbox2.Spacing = 6; + // Container child hbox2.Gtk.Box+BoxChild + this.vbox3 = new global::Gtk.VBox(); + this.vbox3.Name = "vbox3"; + this.vbox3.Spacing = 6; + // Container child vbox3.Gtk.Box+BoxChild this.hbox26 = new global::Gtk.HBox(); this.hbox26.Name = "hbox26"; this.hbox26.Spacing = 6; @@ -99,12 +141,12 @@ namespace osrepodbmgr w5.Position = 2; w5.Expand = false; w5.Fill = false; - w1.Add(this.hbox26); - global::Gtk.Box.BoxChild w6 = ((global::Gtk.Box.BoxChild)(w1[this.hbox26])); + this.vbox3.Add(this.hbox26); + global::Gtk.Box.BoxChild w6 = ((global::Gtk.Box.BoxChild)(this.vbox3[this.hbox26])); w6.Position = 0; w6.Expand = false; w6.Fill = false; - // Container child vbox5.Gtk.Box+BoxChild + // Container child vbox3.Gtk.Box+BoxChild this.hbox25 = new global::Gtk.HBox(); this.hbox25.Name = "hbox25"; this.hbox25.Spacing = 6; @@ -140,12 +182,12 @@ namespace osrepodbmgr w10.Position = 2; w10.Expand = false; w10.Fill = false; - w1.Add(this.hbox25); - global::Gtk.Box.BoxChild w11 = ((global::Gtk.Box.BoxChild)(w1[this.hbox25])); + this.vbox3.Add(this.hbox25); + global::Gtk.Box.BoxChild w11 = ((global::Gtk.Box.BoxChild)(this.vbox3[this.hbox25])); w11.Position = 1; w11.Expand = false; w11.Fill = false; - // Container child vbox5.Gtk.Box+BoxChild + // Container child vbox3.Gtk.Box+BoxChild this.hbox24 = new global::Gtk.HBox(); this.hbox24.Name = "hbox24"; this.hbox24.Spacing = 6; @@ -181,12 +223,12 @@ namespace osrepodbmgr w15.Position = 2; w15.Expand = false; w15.Fill = false; - w1.Add(this.hbox24); - global::Gtk.Box.BoxChild w16 = ((global::Gtk.Box.BoxChild)(w1[this.hbox24])); + this.vbox3.Add(this.hbox24); + global::Gtk.Box.BoxChild w16 = ((global::Gtk.Box.BoxChild)(this.vbox3[this.hbox24])); w16.Position = 2; w16.Expand = false; w16.Fill = false; - // Container child vbox5.Gtk.Box+BoxChild + // Container child vbox3.Gtk.Box+BoxChild this.hbox23 = new global::Gtk.HBox(); this.hbox23.Name = "hbox23"; this.hbox23.Spacing = 6; @@ -222,21 +264,21 @@ namespace osrepodbmgr w20.Position = 2; w20.Expand = false; w20.Fill = false; - w1.Add(this.hbox23); - global::Gtk.Box.BoxChild w21 = ((global::Gtk.Box.BoxChild)(w1[this.hbox23])); + this.vbox3.Add(this.hbox23); + global::Gtk.Box.BoxChild w21 = ((global::Gtk.Box.BoxChild)(this.vbox3[this.hbox23])); w21.Position = 3; w21.Expand = false; w21.Fill = false; - // Container child vbox5.Gtk.Box+BoxChild + // Container child vbox3.Gtk.Box+BoxChild this.lblUnarVersion = new global::Gtk.Label(); this.lblUnarVersion.Name = "lblUnarVersion"; this.lblUnarVersion.LabelProp = global::Mono.Unix.Catalog.GetString("label1"); - w1.Add(this.lblUnarVersion); - global::Gtk.Box.BoxChild w22 = ((global::Gtk.Box.BoxChild)(w1[this.lblUnarVersion])); + this.vbox3.Add(this.lblUnarVersion); + global::Gtk.Box.BoxChild w22 = ((global::Gtk.Box.BoxChild)(this.vbox3[this.lblUnarVersion])); w22.Position = 4; w22.Expand = false; w22.Fill = false; - // Container child vbox5.Gtk.Box+BoxChild + // Container child vbox3.Gtk.Box+BoxChild this.hbox1 = new global::Gtk.HBox(); this.hbox1.Name = "hbox1"; this.hbox1.Spacing = 6; @@ -257,11 +299,159 @@ namespace osrepodbmgr w24.Position = 1; w24.Expand = false; w24.Fill = false; - w1.Add(this.hbox1); - global::Gtk.Box.BoxChild w25 = ((global::Gtk.Box.BoxChild)(w1[this.hbox1])); + this.vbox3.Add(this.hbox1); + global::Gtk.Box.BoxChild w25 = ((global::Gtk.Box.BoxChild)(this.vbox3[this.hbox1])); w25.Position = 5; w25.Expand = false; w25.Fill = false; + this.hbox2.Add(this.vbox3); + global::Gtk.Box.BoxChild w26 = ((global::Gtk.Box.BoxChild)(this.hbox2[this.vbox3])); + w26.Position = 0; + w26.Expand = false; + w26.Fill = false; + // Container child hbox2.Gtk.Box+BoxChild + this.vbox4 = new global::Gtk.VBox(); + this.vbox4.Name = "vbox4"; + this.vbox4.Spacing = 6; + // Container child vbox4.Gtk.Box+BoxChild + this.chkAntivirus = new global::Gtk.CheckButton(); + this.chkAntivirus.CanFocus = true; + this.chkAntivirus.Name = "chkAntivirus"; + this.chkAntivirus.Label = global::Mono.Unix.Catalog.GetString("Use antivirus?"); + this.chkAntivirus.DrawIndicator = true; + this.chkAntivirus.UseUnderline = true; + this.vbox4.Add(this.chkAntivirus); + global::Gtk.Box.BoxChild w27 = ((global::Gtk.Box.BoxChild)(this.vbox4[this.chkAntivirus])); + w27.Position = 0; + w27.Expand = false; + w27.Fill = false; + // Container child vbox4.Gtk.Box+BoxChild + this.frmClamd = new global::Gtk.Frame(); + this.frmClamd.Name = "frmClamd"; + this.frmClamd.ShadowType = ((global::Gtk.ShadowType)(0)); + // Container child frmClamd.Gtk.Container+ContainerChild + this.GtkAlignment6 = new global::Gtk.Alignment(0F, 0F, 1F, 1F); + this.GtkAlignment6.Name = "GtkAlignment6"; + this.GtkAlignment6.LeftPadding = ((uint)(12)); + // Container child GtkAlignment6.Gtk.Container+ContainerChild + this.vbox6 = new global::Gtk.VBox(); + this.vbox6.Name = "vbox6"; + this.vbox6.Spacing = 6; + // Container child vbox6.Gtk.Box+BoxChild + this.chkClamd = new global::Gtk.CheckButton(); + this.chkClamd.CanFocus = true; + this.chkClamd.Name = "chkClamd"; + this.chkClamd.Label = global::Mono.Unix.Catalog.GetString("Use clamd?"); + this.chkClamd.DrawIndicator = true; + this.chkClamd.UseUnderline = true; + this.vbox6.Add(this.chkClamd); + global::Gtk.Box.BoxChild w28 = ((global::Gtk.Box.BoxChild)(this.vbox6[this.chkClamd])); + w28.Position = 0; + w28.Expand = false; + w28.Fill = false; + // Container child vbox6.Gtk.Box+BoxChild + this.hbox3 = new global::Gtk.HBox(); + this.hbox3.Name = "hbox3"; + this.hbox3.Spacing = 6; + // Container child hbox3.Gtk.Box+BoxChild + this.lblClamdHost = new global::Gtk.Label(); + this.lblClamdHost.Name = "lblClamdHost"; + this.lblClamdHost.LabelProp = global::Mono.Unix.Catalog.GetString("Host"); + this.hbox3.Add(this.lblClamdHost); + global::Gtk.Box.BoxChild w29 = ((global::Gtk.Box.BoxChild)(this.hbox3[this.lblClamdHost])); + w29.Position = 0; + w29.Expand = false; + w29.Fill = false; + // Container child hbox3.Gtk.Box+BoxChild + this.txtClamdHost = new global::Gtk.Entry(); + this.txtClamdHost.CanFocus = true; + this.txtClamdHost.Name = "txtClamdHost"; + this.txtClamdHost.IsEditable = true; + this.txtClamdHost.InvisibleChar = '●'; + this.hbox3.Add(this.txtClamdHost); + global::Gtk.Box.BoxChild w30 = ((global::Gtk.Box.BoxChild)(this.hbox3[this.txtClamdHost])); + w30.Position = 1; + // Container child hbox3.Gtk.Box+BoxChild + this.lblClamdPort = new global::Gtk.Label(); + this.lblClamdPort.Name = "lblClamdPort"; + this.lblClamdPort.LabelProp = global::Mono.Unix.Catalog.GetString("port"); + this.hbox3.Add(this.lblClamdPort); + global::Gtk.Box.BoxChild w31 = ((global::Gtk.Box.BoxChild)(this.hbox3[this.lblClamdPort])); + w31.Position = 2; + w31.Expand = false; + w31.Fill = false; + // Container child hbox3.Gtk.Box+BoxChild + this.spClamdPort = new global::Gtk.SpinButton(1, 65535, 1); + this.spClamdPort.CanFocus = true; + this.spClamdPort.Name = "spClamdPort"; + this.spClamdPort.Adjustment.PageIncrement = 10; + this.spClamdPort.ClimbRate = 1; + this.spClamdPort.Numeric = true; + this.spClamdPort.Value = 3310; + this.hbox3.Add(this.spClamdPort); + global::Gtk.Box.BoxChild w32 = ((global::Gtk.Box.BoxChild)(this.hbox3[this.spClamdPort])); + w32.Position = 3; + w32.Expand = false; + w32.Fill = false; + // Container child hbox3.Gtk.Box+BoxChild + this.btnClamdTest = new global::Gtk.Button(); + this.btnClamdTest.CanFocus = true; + this.btnClamdTest.Name = "btnClamdTest"; + this.btnClamdTest.UseUnderline = true; + this.btnClamdTest.Label = global::Mono.Unix.Catalog.GetString("Test"); + this.hbox3.Add(this.btnClamdTest); + global::Gtk.Box.BoxChild w33 = ((global::Gtk.Box.BoxChild)(this.hbox3[this.btnClamdTest])); + w33.Position = 4; + w33.Expand = false; + w33.Fill = false; + this.vbox6.Add(this.hbox3); + global::Gtk.Box.BoxChild w34 = ((global::Gtk.Box.BoxChild)(this.vbox6[this.hbox3])); + w34.Position = 1; + w34.Expand = false; + w34.Fill = false; + // Container child vbox6.Gtk.Box+BoxChild + this.lblClamdVersion = new global::Gtk.Label(); + this.lblClamdVersion.Name = "lblClamdVersion"; + this.lblClamdVersion.LabelProp = global::Mono.Unix.Catalog.GetString("label4"); + this.vbox6.Add(this.lblClamdVersion); + global::Gtk.Box.BoxChild w35 = ((global::Gtk.Box.BoxChild)(this.vbox6[this.lblClamdVersion])); + w35.Position = 2; + w35.Expand = false; + w35.Fill = false; + // Container child vbox6.Gtk.Box+BoxChild + this.chkClamdIsLocal = new global::Gtk.CheckButton(); + this.chkClamdIsLocal.CanFocus = true; + this.chkClamdIsLocal.Name = "chkClamdIsLocal"; + this.chkClamdIsLocal.Label = global::Mono.Unix.Catalog.GetString("Clamd is local?"); + this.chkClamdIsLocal.DrawIndicator = true; + this.chkClamdIsLocal.UseUnderline = true; + this.vbox6.Add(this.chkClamdIsLocal); + global::Gtk.Box.BoxChild w36 = ((global::Gtk.Box.BoxChild)(this.vbox6[this.chkClamdIsLocal])); + w36.Position = 3; + w36.Expand = false; + w36.Fill = false; + this.GtkAlignment6.Add(this.vbox6); + this.frmClamd.Add(this.GtkAlignment6); + this.GtkLabel7 = new global::Gtk.Label(); + this.GtkLabel7.Name = "GtkLabel7"; + this.GtkLabel7.LabelProp = global::Mono.Unix.Catalog.GetString("clamd"); + this.GtkLabel7.UseMarkup = true; + this.frmClamd.LabelWidget = this.GtkLabel7; + this.vbox4.Add(this.frmClamd); + global::Gtk.Box.BoxChild w39 = ((global::Gtk.Box.BoxChild)(this.vbox4[this.frmClamd])); + w39.Position = 1; + w39.Expand = false; + w39.Fill = false; + this.hbox2.Add(this.vbox4); + global::Gtk.Box.BoxChild w40 = ((global::Gtk.Box.BoxChild)(this.hbox2[this.vbox4])); + w40.Position = 1; + w40.Expand = false; + w40.Fill = false; + w1.Add(this.hbox2); + global::Gtk.Box.BoxChild w41 = ((global::Gtk.Box.BoxChild)(w1[this.hbox2])); + w41.Position = 0; + w41.Expand = false; + w41.Fill = false; // Container child vbox5.Gtk.Box+BoxChild this.hbox18 = new global::Gtk.HBox(); this.hbox18.Name = "hbox18"; @@ -274,10 +464,10 @@ namespace osrepodbmgr this.btnCancel.UseUnderline = true; this.btnCancel.Label = "gtk-cancel"; this.hbox18.Add(this.btnCancel); - global::Gtk.Box.BoxChild w26 = ((global::Gtk.Box.BoxChild)(this.hbox18[this.btnCancel])); - w26.Position = 0; - w26.Expand = false; - w26.Fill = false; + global::Gtk.Box.BoxChild w42 = ((global::Gtk.Box.BoxChild)(this.hbox18[this.btnCancel])); + w42.Position = 0; + w42.Expand = false; + w42.Fill = false; // Container child hbox18.Gtk.Box+BoxChild this.btnApply = new global::Gtk.Button(); this.btnApply.CanFocus = true; @@ -286,19 +476,19 @@ namespace osrepodbmgr this.btnApply.UseUnderline = true; this.btnApply.Label = "gtk-apply"; this.hbox18.Add(this.btnApply); - global::Gtk.Box.BoxChild w27 = ((global::Gtk.Box.BoxChild)(this.hbox18[this.btnApply])); - w27.PackType = ((global::Gtk.PackType)(1)); - w27.Position = 1; - w27.Expand = false; - w27.Fill = false; + global::Gtk.Box.BoxChild w43 = ((global::Gtk.Box.BoxChild)(this.hbox18[this.btnApply])); + w43.PackType = ((global::Gtk.PackType)(1)); + w43.Position = 1; + w43.Expand = false; + w43.Fill = false; w1.Add(this.hbox18); - global::Gtk.Box.BoxChild w28 = ((global::Gtk.Box.BoxChild)(w1[this.hbox18])); - w28.Position = 6; - w28.Expand = false; - w28.Fill = false; + global::Gtk.Box.BoxChild w44 = ((global::Gtk.Box.BoxChild)(w1[this.hbox18])); + w44.Position = 1; + w44.Expand = false; + w44.Fill = false; // Internal child osrepodbmgr.dlgSettings.ActionArea - global::Gtk.HButtonBox w29 = this.ActionArea; - w29.Name = "__gtksharp_108_Stetic_TopLevelDialog_ActionArea"; + global::Gtk.HButtonBox w45 = this.ActionArea; + w45.Name = "__gtksharp_108_Stetic_TopLevelDialog_ActionArea"; // Container child __gtksharp_108_Stetic_TopLevelDialog_ActionArea.Gtk.ButtonBox+ButtonBoxChild this.btnDialog = new global::Gtk.Button(); this.btnDialog.CanFocus = true; @@ -306,22 +496,25 @@ namespace osrepodbmgr this.btnDialog.UseUnderline = true; this.btnDialog.Label = global::Mono.Unix.Catalog.GetString("GtkButton"); this.AddActionWidget(this.btnDialog, 0); - global::Gtk.ButtonBox.ButtonBoxChild w30 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w29[this.btnDialog])); - w30.Expand = false; - w30.Fill = false; + global::Gtk.ButtonBox.ButtonBoxChild w46 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w45[this.btnDialog])); + w46.Expand = false; + w46.Fill = false; if((this.Child != null)) { this.Child.ShowAll(); } - this.DefaultWidth = 400; + this.DefaultWidth = 680; this.DefaultHeight = 250; this.lblUnarVersion.Hide(); - w29.Hide(); + w45.Hide(); this.Show(); this.btnDatabase.Clicked += new global::System.EventHandler(this.OnBtnDatabaseClicked); this.btnRepository.Clicked += new global::System.EventHandler(this.OnBtnRepositoryClicked); this.btnTmp.Clicked += new global::System.EventHandler(this.OnBtnTmpClicked); this.btnUnar.Clicked += new global::System.EventHandler(this.OnBtnUnarClicked); + this.chkAntivirus.Toggled += new global::System.EventHandler(this.OnChkAntivirusToggled); + this.chkClamd.Toggled += new global::System.EventHandler(this.OnChkClamdToggled); + this.btnClamdTest.Clicked += new global::System.EventHandler(this.OnBtnClamdTestClicked); this.btnCancel.Clicked += new global::System.EventHandler(this.OnBtnCancelClicked); this.btnApply.Clicked += new global::System.EventHandler(this.OnBtnApplyClicked); }