From 61f0242dbd81e19dfb7ecc41a410b2f56cae8d5a Mon Sep 17 00:00:00 2001 From: "kenb@programmer.net" Date: Sat, 10 Sep 2011 12:06:11 +0000 Subject: [PATCH] aDDED Monitor.SQL Plugin git-svn-id: https://duplicati.googlecode.com/svn/trunk@881 59da171f-624f-0410-aa54-27559c288bec --- .../Monitor.SQL/BackupsDataSetSupport.cs | 83 + .../Duplicati.Scheduler.Monitor.SQL.csproj | 120 ++ Duplicati/Scheduler/Monitor.SQL/Plugin.cs | 78 + .../Monitor.SQL/Properties/AssemblyInfo.cs | 36 + .../Properties/Settings.Designer.cs | 26 + .../Monitor.SQL/Properties/Settings.settings | 5 + .../SQLConnectionDialog.Designer.cs | 228 +++ .../Monitor.SQL/SQLConnectionDialog.cs | 149 ++ .../Monitor.SQL/SQLConnectionDialog.resx | 636 +++++++ .../Monitor.SQL/SQLHistoryDataSet.Designer.cs | 1561 +++++++++++++++++ .../Monitor.SQL/SQLHistoryDataSet.xsc | 9 + .../Monitor.SQL/SQLHistoryDataSet.xsd | 152 ++ .../Monitor.SQL/SQLHistoryDataSet.xss | 1 + .../Scheduler/Monitor.SQL/SettingsSupport.cs | 25 + Duplicati/Scheduler/Monitor.SQL/app.config | 6 + Duplicati/Scheduler/ShellIcons.cs | 138 ++ 16 files changed, 3253 insertions(+) create mode 100644 Duplicati/Scheduler/Monitor.SQL/BackupsDataSetSupport.cs create mode 100644 Duplicati/Scheduler/Monitor.SQL/Duplicati.Scheduler.Monitor.SQL.csproj create mode 100644 Duplicati/Scheduler/Monitor.SQL/Plugin.cs create mode 100644 Duplicati/Scheduler/Monitor.SQL/Properties/AssemblyInfo.cs create mode 100644 Duplicati/Scheduler/Monitor.SQL/Properties/Settings.Designer.cs create mode 100644 Duplicati/Scheduler/Monitor.SQL/Properties/Settings.settings create mode 100644 Duplicati/Scheduler/Monitor.SQL/SQLConnectionDialog.Designer.cs create mode 100644 Duplicati/Scheduler/Monitor.SQL/SQLConnectionDialog.cs create mode 100644 Duplicati/Scheduler/Monitor.SQL/SQLConnectionDialog.resx create mode 100644 Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.Designer.cs create mode 100644 Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.xsc create mode 100644 Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.xsd create mode 100644 Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.xss create mode 100644 Duplicati/Scheduler/Monitor.SQL/SettingsSupport.cs create mode 100644 Duplicati/Scheduler/Monitor.SQL/app.config create mode 100644 Duplicati/Scheduler/ShellIcons.cs diff --git a/Duplicati/Scheduler/Monitor.SQL/BackupsDataSetSupport.cs b/Duplicati/Scheduler/Monitor.SQL/BackupsDataSetSupport.cs new file mode 100644 index 000000000..4f4974ec3 --- /dev/null +++ b/Duplicati/Scheduler/Monitor.SQL/BackupsDataSetSupport.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Duplicati.Scheduler.Monitor.SQL +{ + /// + /// Support for the remote database + /// + /// + /// The goal here was to hit the server as little as possible. + /// So, the data is not parsed from its XML and only the changes are sent. + /// + public partial class SQLHistoryDataSet + { + /// + /// Get the time that the last update was done for this user/machine/entryType + /// + /// Kind to search for + /// Last time or Time.Min if never + public static DateTime Latest(EntryKind aEntryKind) + { + SQLHistoryDataSetTableAdapters.HistoryTableAdapter TableAdapter = new SQLHistoryDataSetTableAdapters.HistoryTableAdapter(); + DateTime? re = TableAdapter.LatestQuery(Duplicati.Scheduler.Utility.User.UserName, Environment.MachineName, aEntryKind.ToString()); + if (re == null) return DateTime.MinValue; + return (DateTime)re; + } + /// + /// Update a record + /// + /// Domain/User + /// Yeah + /// Kind of entry to update + /// Entry time + /// XML to send + public static void Update(string aUserName, string aMachineName, EntryKind aEntryType, DateTime aModificationDate, string aContent) + { + SQLHistoryDataSetTableAdapters.HistoryTableAdapter TableAdapter = new SQLHistoryDataSetTableAdapters.HistoryTableAdapter(); + SQLHistoryDataSet.HistoryDataTable Table = TableAdapter.GetDataBy(aUserName, aMachineName, aEntryType.ToString(), aModificationDate); + HistoryRow Row = null; + if (Table.Count == 0) + Row = Table.AddHistoryRow(aUserName, aMachineName, aEntryType.ToString(), aModificationDate, aContent); + else + Row = ((HistoryRow)Table.Rows[0]); + Row.XmlContent = aContent; + TableAdapter.Update(Table); + //Console.WriteLine(Row.EntryType + ":" + Row.XmlContent); + } + /// + /// Entry may be one of these, note that Schedule includes Settings + /// + public enum EntryKind + { + Schedule, + History, + Log, + None + }; + /// + /// Row tools + /// + public partial class HistoryRow + { + /// + /// Convert string to EntryKind + /// + public EntryKind ToEntryKind(string aType) + { + if (System.Enum.IsDefined(typeof(EntryKind), aType)) return EntryKind.None; + return (EntryKind)System.Enum.Parse(typeof(EntryKind), aType); + } + /// + /// Sets Entry Type + /// + public EntryKind Entry + { + get { return ToEntryKind(this.EntryType); } + set { this.EntryType = value.ToString(); } + } + } + } +} diff --git a/Duplicati/Scheduler/Monitor.SQL/Duplicati.Scheduler.Monitor.SQL.csproj b/Duplicati/Scheduler/Monitor.SQL/Duplicati.Scheduler.Monitor.SQL.csproj new file mode 100644 index 000000000..c000f5bb4 --- /dev/null +++ b/Duplicati/Scheduler/Monitor.SQL/Duplicati.Scheduler.Monitor.SQL.csproj @@ -0,0 +1,120 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {ECA674A3-CC59-4C75-90E3-5AACA591EC5D} + Library + Properties + Duplicati.Scheduler.Monitor.SQL + Duplicati.Scheduler.Monitor.SQL + v3.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + 3.5 + + + 3.5 + + + + + 3.5 + + + 3.5 + + + + + + + Component + + + Form + + + SQLConnectionDialog.cs + + + + True + True + Settings.settings + + + + True + True + SQLHistoryDataSet.xsd + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + SQLHistoryDataSet.xsd + + + Designer + MSDataSetGenerator + SQLHistoryDataSet.Designer.cs + + + SQLHistoryDataSet.xsd + + + + + {C8F0DD19-E242-4E9C-A707-2FFADE8D7970} + Duplicati.Scheduler.Data + + + {0E3DF716-5657-4B51-9BF2-3791880930E1} + Duplicati.Scheduler.Utility + + + + + + SQLConnectionDialog.cs + + + + + + + + \ No newline at end of file diff --git a/Duplicati/Scheduler/Monitor.SQL/Plugin.cs b/Duplicati/Scheduler/Monitor.SQL/Plugin.cs new file mode 100644 index 000000000..8eaca64c0 --- /dev/null +++ b/Duplicati/Scheduler/Monitor.SQL/Plugin.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Duplicati.Scheduler.Monitor.SQL +{ + /// + /// Maintains the server data + /// + public class Plugin : Duplicati.Scheduler.Data.IMonitorPlugin + { + public string Name { get { return "Monitor.SQL"; } } + /// + /// Update a log entry + /// + /// Date + /// XML content + public void UpdateLog(DateTime aLogDate, string aLogContent) + { + SQLHistoryDataSet.Update(Duplicati.Scheduler.Utility.User.UserName, Environment.MachineName, SQLHistoryDataSet.EntryKind.Log, + aLogDate, aLogContent); + } + /// + /// Update the scheduler record + /// + public void Scheduler() + { + UpdateScheduler(Duplicati.Scheduler.Data.SchedulerDataSet.DefaultPath()); + } + /// + /// Update the scheduler record + /// + /// XML file to load + public void UpdateScheduler(string aScheduler) + { + DateTime LastUpdate = SQLHistoryDataSet.Latest(SQLHistoryDataSet.EntryKind.Schedule); + DateTime LastWrite = System.IO.File.GetLastWriteTime(aScheduler); + if (LastUpdate < LastWrite) + SQLHistoryDataSet.Update(Duplicati.Scheduler.Utility.User.UserName, Environment.MachineName, SQLHistoryDataSet.EntryKind.Schedule, + LastWrite, System.IO.File.ReadAllText(aScheduler)); + } + /// + /// Update History + /// + public void UpdateHistory(string aHistory) + { + using (Duplicati.Scheduler.Data.HistoryDataSet hds = new Duplicati.Scheduler.Data.HistoryDataSet()) + { + hds.Load(); + History(System.IO.File.GetLastWriteTime(aHistory), hds.History); + } + } + /// + /// Update History + /// + /// Date + /// XML file name + public void History(DateTime aLastWrite, Duplicati.Scheduler.Data.HistoryDataSet.HistoryDataTable aHistoryTable) + { + DateTime LastUpdate = SQLHistoryDataSet.Latest(SQLHistoryDataSet.EntryKind.Schedule); + Duplicati.Scheduler.Data.HistoryDataSet.HistoryDataTable Changes = new Duplicati.Scheduler.Data.HistoryDataSet.HistoryDataTable(); + foreach (Duplicati.Scheduler.Data.HistoryDataSet.HistoryRow Row in + from Duplicati.Scheduler.Data.HistoryDataSet.HistoryRow qR in aHistoryTable + where qR.ActionDate > LastUpdate + select qR) + Changes.ImportRow(Row); + StringBuilder b = new StringBuilder(); + Changes.WriteXml(new System.IO.StringWriter(b)); + SQLHistoryDataSet.Update(Duplicati.Scheduler.Utility.User.UserName, Environment.MachineName, SQLHistoryDataSet.EntryKind.History, + aLastWrite, b.ToString()); + } + public System.Windows.Forms.DialogResult Configure() + { + return new SQLConnectionDialog(Properties.Settings.MonitorConnection).ShowDialog(); + } + } +} diff --git a/Duplicati/Scheduler/Monitor.SQL/Properties/AssemblyInfo.cs b/Duplicati/Scheduler/Monitor.SQL/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..918827b72 --- /dev/null +++ b/Duplicati/Scheduler/Monitor.SQL/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Duplicati.Scheduler.Monitor.SQL")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Duplicati.Scheduler.Monitor.SQL")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ee6179d4-89dc-496a-a26e-ead63f35770d")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Duplicati/Scheduler/Monitor.SQL/Properties/Settings.Designer.cs b/Duplicati/Scheduler/Monitor.SQL/Properties/Settings.Designer.cs new file mode 100644 index 000000000..05dcd3046 --- /dev/null +++ b/Duplicati/Scheduler/Monitor.SQL/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4961 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Duplicati.Scheduler.Monitor.SQL.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Duplicati/Scheduler/Monitor.SQL/Properties/Settings.settings b/Duplicati/Scheduler/Monitor.SQL/Properties/Settings.settings new file mode 100644 index 000000000..2bd17f050 --- /dev/null +++ b/Duplicati/Scheduler/Monitor.SQL/Properties/Settings.settings @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Duplicati/Scheduler/Monitor.SQL/SQLConnectionDialog.Designer.cs b/Duplicati/Scheduler/Monitor.SQL/SQLConnectionDialog.Designer.cs new file mode 100644 index 000000000..01de61267 --- /dev/null +++ b/Duplicati/Scheduler/Monitor.SQL/SQLConnectionDialog.Designer.cs @@ -0,0 +1,228 @@ +namespace Duplicati.Scheduler.Monitor.SQL +{ + partial class SQLConnectionDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.Windows.Forms.Label dataSourceLabel; + System.Windows.Forms.Label passwordLabel; + System.Windows.Forms.Label userIDLabel; + System.Windows.Forms.Label label1; + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SQLConnectionDialog)); + this.integratedSecurityCheckBox = new System.Windows.Forms.CheckBox(); + this.passwordTextBox = new System.Windows.Forms.TextBox(); + this.userIDTextBox = new System.Windows.Forms.TextBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.SavePwCheckBox = new System.Windows.Forms.CheckBox(); + this.CanButton = new System.Windows.Forms.Button(); + this.OKButton = new System.Windows.Forms.Button(); + this.TestButton = new System.Windows.Forms.Button(); + this.CatalogTextBox = new System.Windows.Forms.TextBox(); + this.DataSourceComboBox = new System.Windows.Forms.ComboBox(); + dataSourceLabel = new System.Windows.Forms.Label(); + passwordLabel = new System.Windows.Forms.Label(); + userIDLabel = new System.Windows.Forms.Label(); + label1 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // dataSourceLabel + // + dataSourceLabel.AutoSize = true; + dataSourceLabel.Location = new System.Drawing.Point(9, 13); + dataSourceLabel.Name = "dataSourceLabel"; + dataSourceLabel.Size = new System.Drawing.Size(110, 13); + dataSourceLabel.TabIndex = 3; + dataSourceLabel.Text = "Data Source (Server):"; + // + // passwordLabel + // + passwordLabel.AutoSize = true; + passwordLabel.Location = new System.Drawing.Point(13, 48); + passwordLabel.Name = "passwordLabel"; + passwordLabel.Size = new System.Drawing.Size(56, 13); + passwordLabel.TabIndex = 17; + passwordLabel.Text = "Password:"; + // + // userIDLabel + // + userIDLabel.AutoSize = true; + userIDLabel.Location = new System.Drawing.Point(23, 22); + userIDLabel.Name = "userIDLabel"; + userIDLabel.Size = new System.Drawing.Size(46, 13); + userIDLabel.TabIndex = 23; + userIDLabel.Text = "User ID:"; + // + // integratedSecurityCheckBox + // + this.integratedSecurityCheckBox.Location = new System.Drawing.Point(12, 75); + this.integratedSecurityCheckBox.Name = "integratedSecurityCheckBox"; + this.integratedSecurityCheckBox.Size = new System.Drawing.Size(133, 24); + this.integratedSecurityCheckBox.TabIndex = 8; + this.integratedSecurityCheckBox.Text = "Integrated security"; + this.integratedSecurityCheckBox.UseVisualStyleBackColor = true; + this.integratedSecurityCheckBox.CheckedChanged += new System.EventHandler(this.integratedSecurityCheckBox_CheckedChanged); + // + // passwordTextBox + // + this.passwordTextBox.Location = new System.Drawing.Point(75, 45); + this.passwordTextBox.Name = "passwordTextBox"; + this.passwordTextBox.Size = new System.Drawing.Size(163, 20); + this.passwordTextBox.TabIndex = 18; + this.passwordTextBox.UseSystemPasswordChar = true; + // + // userIDTextBox + // + this.userIDTextBox.Location = new System.Drawing.Point(75, 19); + this.userIDTextBox.Name = "userIDTextBox"; + this.userIDTextBox.Size = new System.Drawing.Size(163, 20); + this.userIDTextBox.TabIndex = 24; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.SavePwCheckBox); + this.groupBox1.Controls.Add(this.userIDTextBox); + this.groupBox1.Controls.Add(userIDLabel); + this.groupBox1.Controls.Add(this.passwordTextBox); + this.groupBox1.Controls.Add(passwordLabel); + this.groupBox1.Location = new System.Drawing.Point(35, 93); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(255, 100); + this.groupBox1.TabIndex = 25; + this.groupBox1.TabStop = false; + // + // SavePwCheckBox + // + this.SavePwCheckBox.AutoSize = true; + this.SavePwCheckBox.Location = new System.Drawing.Point(75, 72); + this.SavePwCheckBox.Name = "SavePwCheckBox"; + this.SavePwCheckBox.Size = new System.Drawing.Size(99, 17); + this.SavePwCheckBox.TabIndex = 25; + this.SavePwCheckBox.Text = "Save password"; + this.SavePwCheckBox.UseVisualStyleBackColor = true; + // + // CanButton + // + this.CanButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.CanButton.CausesValidation = false; + this.CanButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.CanButton.Location = new System.Drawing.Point(247, 241); + this.CanButton.Name = "CanButton"; + this.CanButton.Size = new System.Drawing.Size(75, 23); + this.CanButton.TabIndex = 27; + this.CanButton.Text = "Cancel"; + this.CanButton.UseVisualStyleBackColor = true; + this.CanButton.Click += new System.EventHandler(this.CanButton_Click); + // + // OKButton + // + this.OKButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.OKButton.CausesValidation = false; + this.OKButton.Location = new System.Drawing.Point(166, 241); + this.OKButton.Name = "OKButton"; + this.OKButton.Size = new System.Drawing.Size(75, 23); + this.OKButton.TabIndex = 28; + this.OKButton.Text = "OK"; + this.OKButton.UseVisualStyleBackColor = true; + this.OKButton.Click += new System.EventHandler(this.OKButton_Click); + // + // TestButton + // + this.TestButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.TestButton.CausesValidation = false; + this.TestButton.Location = new System.Drawing.Point(12, 241); + this.TestButton.Name = "TestButton"; + this.TestButton.Size = new System.Drawing.Size(75, 23); + this.TestButton.TabIndex = 29; + this.TestButton.Text = "Test"; + this.TestButton.UseVisualStyleBackColor = true; + this.TestButton.Click += new System.EventHandler(this.TestButton_Click); + // + // label1 + // + label1.AutoSize = true; + label1.Location = new System.Drawing.Point(73, 39); + label1.Name = "label1"; + label1.Size = new System.Drawing.Size(46, 13); + label1.TabIndex = 30; + label1.Text = "Catalog:"; + // + // CatalogTextBox + // + this.CatalogTextBox.Location = new System.Drawing.Point(125, 36); + this.CatalogTextBox.Name = "CatalogTextBox"; + this.CatalogTextBox.Size = new System.Drawing.Size(197, 20); + this.CatalogTextBox.TabIndex = 31; + // + // DataSourceComboBox + // + this.DataSourceComboBox.FormattingEnabled = true; + this.DataSourceComboBox.Location = new System.Drawing.Point(125, 10); + this.DataSourceComboBox.Name = "DataSourceComboBox"; + this.DataSourceComboBox.Size = new System.Drawing.Size(197, 21); + this.DataSourceComboBox.TabIndex = 32; + // + // SQLConnectionDialog + // + this.AcceptButton = this.OKButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.CanButton; + this.ClientSize = new System.Drawing.Size(334, 276); + this.Controls.Add(this.DataSourceComboBox); + this.Controls.Add(label1); + this.Controls.Add(this.CatalogTextBox); + this.Controls.Add(this.TestButton); + this.Controls.Add(this.OKButton); + this.Controls.Add(this.CanButton); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.integratedSecurityCheckBox); + this.Controls.Add(dataSourceLabel); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "SQLConnectionDialog"; + this.Text = "SQL Connection"; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.CheckBox integratedSecurityCheckBox; + private System.Windows.Forms.TextBox passwordTextBox; + private System.Windows.Forms.TextBox userIDTextBox; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button CanButton; + private System.Windows.Forms.Button OKButton; + private System.Windows.Forms.Button TestButton; + private System.Windows.Forms.CheckBox SavePwCheckBox; + private System.Windows.Forms.TextBox CatalogTextBox; + private System.Windows.Forms.ComboBox DataSourceComboBox; + } +} \ No newline at end of file diff --git a/Duplicati/Scheduler/Monitor.SQL/SQLConnectionDialog.cs b/Duplicati/Scheduler/Monitor.SQL/SQLConnectionDialog.cs new file mode 100644 index 000000000..8844580a2 --- /dev/null +++ b/Duplicati/Scheduler/Monitor.SQL/SQLConnectionDialog.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace Duplicati.Scheduler.Monitor.SQL +{ + /// + /// Provides a form to edit the SQL connection string + /// + public partial class SQLConnectionDialog : Form + { + /// + /// Encrypted connection string in an XML file + /// + public string HomeConnectionXMLFile { get; set; } + /// + /// Resulting connection string + /// + public string ConnectionString { get; private set; } + /// + /// Builder used to parse/set the string + /// + private System.Data.SqlClient.SqlConnectionStringBuilder ConnectionStringBuilder; + /// + /// Creator + /// + /// Name of XML file to load/save + public SQLConnectionDialog(string aHomeConnectionXMLFile) + { + InitializeComponent(); + // Save the file nae, load the connectin string + this.HomeConnectionXMLFile = aHomeConnectionXMLFile; + this.DataSourceComboBox.Items.Add(Environment.MachineName + @"\SQLEXPRESS"); + this.ConnectionString = new Duplicati.Scheduler.Data.ConnectionFromXML().ConnectionString(aHomeConnectionXMLFile); + } + /// + /// Form loaded, populate the controls + /// + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + try + { + // Parse the string + this.ConnectionStringBuilder = new System.Data.SqlClient.SqlConnectionStringBuilder(this.ConnectionString); + } + catch (Exception Ex) + { + // If error, say it, and clear the connection string + MessageBox.Show(Ex.Message); + this.ConnectionStringBuilder = new System.Data.SqlClient.SqlConnectionStringBuilder(); + } + // Set the controls + this.DataSourceComboBox.Text = this.ConnectionStringBuilder.DataSource; + this.integratedSecurityCheckBox.Checked = this.ConnectionStringBuilder.IntegratedSecurity; + this.userIDTextBox.Text = this.ConnectionStringBuilder.UserID; + this.passwordTextBox.Text = this.ConnectionStringBuilder.Password; + this.SavePwCheckBox.Checked = this.ConnectionStringBuilder.PersistSecurityInfo; + this.CatalogTextBox.Text = this.ConnectionStringBuilder.InitialCatalog; + } + /// + /// Integrated checkbox pressed, enable/disable the login stuff + /// + private void integratedSecurityCheckBox_CheckedChanged(object sender, EventArgs e) + { + this.groupBox1.Enabled = !this.integratedSecurityCheckBox.Checked; + } + /// + /// OK pressed, get the string from the controls and close + /// + private void OKButton_Click(object sender, EventArgs e) + { + // Check if all OK, also loads the string builder from the controls + if (!Parse()) return; + this.ConnectionString = this.ConnectionStringBuilder.ConnectionString; + try + { + // Save the result + new Duplicati.Scheduler.Data.ConnectionFromXML().SaveConnection(this.HomeConnectionXMLFile, + this.ConnectionString); + } + catch (Exception Ex) + { + MessageBox.Show("Error saving connection string: " + this.HomeConnectionXMLFile + ": " + Ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + this.DialogResult = DialogResult.OK; + Close(); + } + /// + /// Gets the connection string builder from the controls + /// + /// True if no errors + private bool Parse() + { + bool Result = false; + try + { + this.ConnectionStringBuilder.DataSource = this.DataSourceComboBox.Text; + this.ConnectionStringBuilder.InitialCatalog = this.CatalogTextBox.Text; + this.ConnectionStringBuilder.IntegratedSecurity = this.integratedSecurityCheckBox.Checked; + if (!this.integratedSecurityCheckBox.Checked) + { + this.ConnectionStringBuilder.UserID = this.userIDTextBox.Text; + this.ConnectionStringBuilder.Password = this.passwordTextBox.Text; + this.ConnectionStringBuilder.PersistSecurityInfo = this.SavePwCheckBox.Checked; + } + Result = true; + } + catch (Exception Ex) + { + MessageBox.Show(Ex.Message); + } + return Result; + } + /// + /// Test pressed, test the connection + /// + private void TestButton_Click(object sender, EventArgs e) + { + // Get the builder + if (!Parse()) return; + try + { + // Open a connection + using (System.Data.SqlClient.SqlConnection oc = new System.Data.SqlClient.SqlConnection( + this.ConnectionStringBuilder.ConnectionString)) + oc.Open(); + MessageBox.Show("Connection succeeded", "SUCCESS", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + catch (Exception Ex) + { + MessageBox.Show("Error connecting: " + Ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + /// + /// Cancel pressed, close + /// + private void CanButton_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.Cancel; + Close(); + } + } +} diff --git a/Duplicati/Scheduler/Monitor.SQL/SQLConnectionDialog.resx b/Duplicati/Scheduler/Monitor.SQL/SQLConnectionDialog.resx new file mode 100644 index 000000000..36bfafbd8 --- /dev/null +++ b/Duplicati/Scheduler/Monitor.SQL/SQLConnectionDialog.resx @@ -0,0 +1,636 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + + False + + + False + + + False + + + + + AAABAAwAMDAQAAEABABoBgAAxgAAACAgEAABAAQA6AIAAC4HAAAYGBAAAQAEAOgBAAAWCgAAEBAQAAEA + BAAoAQAA/gsAADAwAAABAAgAqA4AACYNAAAgIAAAAQAIAKgIAADOGwAAGBgAAAEACADIBgAAdiQAABAQ + AAABAAgAaAUAAD4rAAAwMAAAAQAgAKglAACmMAAAICAAAAEAIACoEAAATlYAABgYAAABACAAiAkAAPZm + AAAQEAAAAQAgAGgEAAB+cAAAKAAAADAAAABgAAAAAQAEAAAAAACABAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA/wAA/wAAAP//AP8AAAD/AP8A//8AAP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4d3d3d3d3 + d3d3d3d3d3d3d3cAAAAAAIeIiPj4+Pj4+Pj4+Pj4+Pj4+Ph4AAAACHh3JyNiNiNiNiNiNiNiNiNiNniH + cAAACIcnInI2I2I2I2I2I2I2I2I2MiN/cAAAh4JyemJjanJ6cnpyenJ6cnpyY2poiAAAiHIqNjOmMjYj + ajY2JycjajYnpycnhwAAiCcnImJyemOoeHh4eHh4eHh4dyMniAAAh3KnJ6cqNjY4////////////h6an + hwAAiCciejJyY6Jn/4+PiPiI+I+P9ycj9wAAiCJ6JyajYnJ4+P+P+Pj4j4iPh6cmiAAAiHo2NqNjp6Ko + /4+Pj4+PiPiP9yJ69wAAiCYno2NiYnJ3//j4iIiIiIj492OniAAAiCOmJjpjo2p4+PiIiIiIiIiPh6Yy + 9wAAiHJzeHd4d3d3//j/j/j4+Ij49yemiAAAiCpqiP/4///4//+P+Pj4j4+Ph6Yz+AAAiHI3j4j4+IiI + +PiIiPiIiIiP9yNqiAAA96emf/j4+Pj3//j4+Ij4+IiPh6aniAAAiHI6j4+PiPiI+P+P/4//j/iP92On + iAAA9yp2iPj4j4iI/4iIj4j4+Pj496cm+AAAiHp6j4+IiIiI//j4j4j//4iPh6ajiAAA+CcjiPiIiIiI + +P//+Pj4+Pj/9yen+AAAiCp6j////4+I/4iIj4j4+PiPh6ei9wAAiHpjiIiIiIiI//iIj4iIiIj/96Y2 + +AAA+Cenj/+IiPiIj4//////+Pj492p6iAAAiKeniPj/j4iI//+Pj4+Pj4+Ph6en+AAAiHp6j/+IiPj4 + +P///////4iIiHp6iAAA+Cd3j4+I+PiI/4+Pj4+Pj4iIhqh3+AAAiKeoj/j/j4+I////////+I+Id3p6 + iAAAiHeniP+I+PiI/4+Pj4+Pj4iIp6in9wAAiKeKj/j4iPj4////////+IiGiod6+AAAiDqHj/+P+P+I + +Pj4+Pj4/4eoqKiniAAAiGioj4/4/4/4iIiIiIiIeH53d3qK9wAAiKeKj/j/j/j///iPiH6neoqKioh6 + 9wAAiHqIj/+P+P+Pj4iIiIeKiKiHeKin9wAAh6h3j4/4/4//+Pj4iKiod4qKioiKiAAA93d3j///j/j4 + /4j4joeHd4eHiKin9wAAiKh4j4+P////j/iId3eoeoqKh4eKiAAAiDioj///j4+P+PiOuKiIeIiIqKh6 + 9wAA92eIiIiIiIiIiIh4qIiod6ioiId3iAAAiHqKh4eHiHiHjod4iKiIeIiHd3eohwAAD3eoioeKh4qH + h3h3eIioioeHh6eHgAAACIh3p6p6emp6qqqqqqenp6qqp3h4cAAAAIiHh4eHh4h4eIiIh4eHeHh4h4eI + AAAAAACIiIiIiIiIiIiIiIiIiIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD///////8AAP///////wAA/AAAAAA/AADwAAAAAA8AAOAAAAAABwAA4AAAAAAH + AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAA + AAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAAD + AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAA + AAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAAD + AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADgAAAAAAcAAOAA + AAAABwAA8AAAAAAPAAD8AAAAAD8AAP///////wAA////////AAAoAAAAIAAAAEAAAAABAAQAAAAAAAAC + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICAgADAwMAAAAD/AAD/ + AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAAAAAAAAAId3d3d3d3d3d3d3eAAAAAeIiHiI + eIh4iHiIeIhwAACHciJyInIiciJyInInhwAIgicnononpypypyejYniACHcqcnI2d3d3d3d3d3oocAhy + ciKnInj///////hyeHAIenJ6cnp4+Pj4iIj/aihwCHJ6cmOmP/+Pj/j4j3NogAh6NiOmMn+IiIiIiI9q + OHAIgmeIiIh///+PiI+PcmiACHOn+PiPiPiI+IiIj2OocAiCd/j4+I//j4j/+P96eIAIemf4+IiPj4j4 + +PiPY6hwCIKo+IiIiPj4+P+I/2pogAh3p//4+I/4+PiP+PhzqHAIinf4iIiPj4j4iIj/aniACHp3/4/4 + j//////4+HeocAiHqPiIj4j4+Pj4+Ih6eIAIenj//4+P/////4j3eniACIeo+Ij4j4+Pj4+IioeocAh6 + iI/4/4//////iH6oqIAIh6j/j4+IiIiHeOeod4hwCHqI//////iIjqioiop4cAh4ePj4+Pj4+HiKh3h4 + qIAIeoj/////+Ih6iHioqIhwCHio+I+I+IiOiKh4h4eocAiKiIiIiOiId3iHeoeHqIAAh3qKinqKioqK + ioiop4gAAAiHd3eHd3d3d3d3d4hwAAAAiIiIiIiIiIiIiIiIAAAAAAAAAAAAAAAAAAAAAAAA//////AA + AA/gAAAHwAAAA4AAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAcAAAAPgAAAH8AAAD/// + //8oAAAAGAAAADAAAAABAAQAAAAAACABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAA + AACAAIAAgIAAAICAgADAwMAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAACI + iIiIiIiIiIh4AAh3IiIiIiIiIid4gAhycnNnNnNnNjIngAgiNiY2iIiIiPgigAh6Y6On////j4hjgAgj + anYn/4iI+IimgAhqdzd3+Pj4iPgjgAg2j4+I/4+IiIhqgAgjj4+I+Pj/+PgngAh6j4iI+I+I+PimgAin + j4+I//j/iPgjgAh6j4iI+I+I+Pim8Ainj4+I////+Ih6gAh3j4+I/4+PiIengAinj4j4////+IqK8Ah3 + j//4iIiIiGh3gAioj4+P+PiKioqKgAh4j///+IjoeHiogAioj/j4+IioqKiKgAh4iIiIiHiIiIeHgAiK + enp6eoqnp6iogACIiIiIiIiIiIiIAAAAAAAAAAAAAAAAAP///wDAAAMAgAABAIAAAQCAAAEAgAABAIAA + AQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAA + AQDAAAMA////ACgAAAAQAAAAIAAAAAEABAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACA + AAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AAD///8AAAAAAAAA + AAAId3d3d3d3gAcioqenp6JwB6cnj4+P93AHInKI+IiGcAd4iI+Pj/KACn+Pj4+I9jAHeIiPj/j3oAev + +P+Pj4eAB4j4j//4ioAHf4+P+PiGgAeI//iId6igCo/4+Iioh4AIiIiIh4d4oAh6h3qKioeAAAAAAAAA + AAD//wAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIAB + AAD//wAAKAAAADAAAABgAAAAAQAIAAAAAAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAvkS8AL5YvAC+a + LwAvnS8ANYk1ADWMNQA/hj8AN484ADiPOAAwkTAAMJUwADaRNgA2lTYAMJgwADCeMAA3kzgAOJQ4ADiZ + OAA5nTkAMKMwADigNwAwqzAAOqE6ADumOwA8ojwAPaY8ADyrPAAxsDEAPbQ9AECLQABdi10AQK9BAEK0 + QgBDu0QATb5NAFukXABZvlkAYY1hAGGQYgBrkGkAdJJyAHWUcwB2lnQAd5h0AHicdgB8n3oAYaphAH6i + fAB7sXkARMREAEjASABUwlQAW8ZbAF/KXwBjxWMAY8xjAGrMagBr0WsAbNpsAHPUcwB22HYAe9V7AHzZ + fACAk30AgaJ/AIDXfwCLi4sAi4uMAI2NjgCFkYEAg5eDAIaShQCIlIQAiZWIAI+PkACRkZIAlJaQAJSU + lQCWmZMAl5qUAJiblQCZnJYAl5eYAJiYmQCbnpgAnJ6YAJqanACdnZ0AhKSFAI+jjwCGsIQAi7OJAJC1 + jwCYoZkAnaCaAJq6mACjp58An5+gAKGhogCjpKAApaaiAKOjpACkpKYAqqamAKOooAClqaEApqikAKio + pACnp6gAp66oAKioqQCrrKgAqqqsAKysrgCyrq0AqrSoALOwrwCurrAAsLCyALWxsQC2tbIAs7O0ALa2 + tgC8tbIAtby1ALq5tQC5uLkAvbq6AL2+ugC+vLwAwreyAMK4swDBubYAxbq2AMG8uQDGvbkAwb+/AMW/ + vADIv7wAgt2CAIrdigCSwpEAmcSXAJ7AnQCF4IUAi+KLAJPkkwClwaIAqcOnAK/HrQCzzrEAvsy8AMPA + vgDIwb4AwM2+AMHBwADFwsEAxcXCAMPDxADGxcYAy8PAAMrEwQDMxcIAyMbFAM3HxADCzcAAzcjGAMnJ + yADNysgAy8zJAM3OywDNzc4A2s3HAN3MxgDSzcoA2M7JAN7OyADP0M0A1dDOAN7QygDa0s0A3tHNAM/P + 0ADR0dEA1tLQANPT1ADV1dUA29XSAN7Y1QDX19gA2dnZANvb3ADc3N0A4dHKAODTzQDk08wA4tTPAOXV + zgDr1s4A7NfOAOzYzwDh1tIA5tfQAOjX0ADm2NIA4drWAOXa1QDo2dMA7drSAO3c0wDp2tQA7tvUAOnc + 1gDu3dUA4tzZAOXd2gDh390A5d/cAOne2QDt39gA8N/XAOXg3QDr4d0A8OHaAPDi3ADx5N4A4+LhAOrk + 4ADs5eEA6ubkAOzn5ADu6OUA6urpAOvs6wDv7+0A8ubgAPLo4gDx6eYA9OrmAPTs5wDw6+gA8u3qAPXu + 6gDz7uwA9O/tAPbw7QD48u8A8vLxAPn08QD5+PcA+fn4AAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUU1NERERERERERERERERERERERERERERERERE + RERERERERFMAAAAAAAAAAAAAZ2dUiauruLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLjAuHJEVAAA + AAAAAAByZ2duHwcFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUHJ324S1QAAAAAAACeZ0cFCgoK + AQoBAQEKAQEKAQEKAQEKAQEKAQEKAQoBAQoBAQoKCgVauFMAAAAAAH9tVAUKCgoKCgoKCgoKCgoKCgoK + CgoKCgoKCgoKCgoKCgoKCgoKCgoJfXpTAAAAALhnHwELAQEKAQoBAQEKAQEKCgkSCQkJEgkJCRIJCQkS + CQkJEgkKCgoBJ8BTAAAAALhUHgEKAQEKAQoBAQEKAQESSmFfX19fX19fVVVVVVVVUVVRUVEoAQoBHsBV + AAAAAKtUCRICAhIBAhIBAhIBAhISYfv7+/v7+/v7+/v7+/r6+vr7++kpChICCr5TAAAAALdUEQECAgIC + AgICAgICAgESYfvw8Ozs7Ozd3d3d3cnd3cnd3ekpAgICCbhUAAAAALhUCQ8PAQICAgICAgICAgIVavvw + 7Ozs3d3d3d3HycnHx8fH7OkpAgICCcBUAAAAALhnEQIPAgIPAgIPAgIPAg8Vavvw8PDs7Ozs3d3d3cfJ + x8fH3ekpAhUCEr5nAAAAALhnChICDwIUAhQCDw8PAg8Vavvw8N3OzsXFtraxsbGurq7H7OksAg8CEr5n + AAAAALhnEg8PDxQUFQ8PDw8PDw8Xavv38KShoaGIiIiGhoaGg4PH7OkpDw8PEr9nAAAAALhnEg8PFUBH + R0dHR0dGRkZHaPv28PDn593n3dvb3c7dxczd7OksDw8PE79nAAAAALhyEhQUF2fp6enp6enp6enncvv2 + 9vDw6e3w8N3n293O3d3M7OksFBQPE8BuAAAAALhyEhQVF2Hw59vb293O3c7Fc/v28KSkpaHavaSkiIiI + hobd8OksFBQUE8ByAAAAAMByFw8WF2rp3dvdxc7HxcWxc/v29trazs7wvbbn3efd2ojb8OksFBUPF8By + AAAAALhyFxYWGmr43d7a293FzsfFc/v29vD38/P3vbbw8PDw7Yjd8OksFhYWF8ByAAAAAMByFxYVGmrr + 593Oxb22xa6uc/v28LOvr6fnvb329vDw8Ijp8OktFBQWF8B2AAAAAL92FxYWGmrr6dqIf4Z8fHx8c/v2 + 9raztq/tvb3w9vfw8KHt8OktFhYWF8B6AAAAAL92GhwWHXDr593Avb22tranc/v39vb28Pbwvb3w9vf3 + 8J7w9+ktFhYWGsF2AAAAAMB2GhwWHWfr5+fd593j3d7devv38L29vb3pva/n3ePn3Z7w9ukuHBYcGsF6 + AAAAAMB2GhwcHXDp6d2eiYl/3q+Ic/v28K+ppKTd2qukqaSkpKTw+ekuHBwcGsF6AAAAAMB2HSIdIXL2 + 596vr6+n3amkevv29vDw8/D28PDw8PDw8PDw8OkuIiIiHcB6AAAAAL92HSMjJXr26fDn6fDp6a+zfvv3 + 9vf39/P58Pn58/fw59ra4+MuIyMjIMB2AAAAAL9yITQ0NXz48Oe2s7Oz3bi9ifv59/f39/n5+ff5+fnw + r56IqKtBNDQ0IcB2AAAAAL5yHTQlN3746eevr6+p6ba4ofv59/f39/f39/f38/nnc6ief2gxNDQ0IcB2 + AAAAALh2ITU1OH/48Onw6fDp8L29nvv59/f59/f59/f5+fPngOnZiVs1NTU1IcByAAAAAMByHTg1OYH4 + 8Ona2trO6b24qfv5+fn5+fn5+fn3+fnnf9mJXDg2NTg1IsByAAAAALhyHTg4OZ748Omvr6un3cCvnvv7 + +fv5+/n7+fn5+fnwiaBdOTg4ODg4IsBuAAAAALhnIjk6PIn48PDp6fDp6fDnpPj4+Pj4+Pj4+Pj4+Pjp + e2A5OTo6Ojo6IsBnAAAAALhnIjo6PKT49unw8PDw8Onwr6urpKSknqSedpSUlJSUjzw6Ojo6Ojo6IsBn + AAAAALhnIjw8PqT66fbw8Pjw+PD48PDw6b2vqbezXTw8PD08PDw8PDw8PDw8M71jAAAAALhhIj09Qqv4 + 9vD48Pjw8Pjw+PD424CeiYl6jj09PT09PT09PT09PT09M75jAAAAALdUIj1CQqv49vbw+PD4+PD48Pjw + 457p2aiQPUI9jD2MPYw9jD2MPYw9I7hjAAAAALdUM4yMkqv4+Pjw+Pj48Pjw+PD446jZt5RCjIyMQoxC + QoyMjEKMjIyMI75UAAAAALhUMoyMkrP4+Pj4+Pj3+Pj4+Pj456i3lY2MkYySjJKMkpKMkoySjIyMMrhU + AAAAAMBUIZKSk7L4+Pn4+Pj4+Pj3+Pn46YmWjZKSkpKSkpKSkpKSkpKSkpKRI7hjAAAAAMBULzuSk5um + pqampqSmpJukm6Sbm5eTjZKSk5KSkpKSkpKSkpKSkpI7L6RUAAAAAH9/SjKSk5OTk5OTk5OTk5OTkpOS + k5OTk5OTk5OTk5OTkpOSk5KTk5IylGNjAAAAAADjUykyPJOTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OT + k5OTk5OTOzJZbW0AAAAAAAB6uFNKJCIyMzMzMzIyMzIyMzI0MjIjMjMzMjMyMzIzMjMyNDIzL15fbm0A + AAAAAAAAesB6U0tMTExNTFFMTUxRTExMTExMTExMTExMTExMTUxNSkxTU2OfcgAAAAAAAAAAAAB6uMCr + pKCgpJ+goKCkn6CboKCfoKCgoKCgoKCgoKCgoKC3t30AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD///////8AAP///////wAA/AAAAAA/AADwAAAAAA8AAOAAAAAABwAA4AAAAAAH + AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAA + AAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAAD + AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAA + AAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAAD + AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADgAAAAAAcAAOAA + AAAABwAA8AAAAAAPAAD8AAAAAD8AAP///////wAA////////AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAE + AAAAAAAAAAAAAAABAAAAAQAAAAAAADCPMAAwkTAAMJYwADCaMAAwnTAAMaIxADGlMQAxqjEAMa0xADKw + MgA1sjUARItEAEWMRQBGlkUATJJLAFWaVABWnlUAXZNcAF6VXABemF0AYJteAGCeXgBGu0YAS79LAEy9 + TABVu1YAYaJfAHmXdwBzm3EAc5p0AHSadAB9kH4Ae5R8AH2XfgB6mHgAfJp6AH6cewB+nXwAYqVgAG+q + bQB0r3IAfaJ+AFHCUQBVx1UAVshWAFrHWgBfw18AWstaAFzMXABnx2YAYcthAGHPYQBoz2gAb8tuAGXS + ZQBo02gAa9ZrAG/TbwBu124AbNpsAHbXdgBy2nIAeNJ4AH3bfQB94H0AhoaGAI2NjQCBlIIAhJKEAIeU + hwCAmoEAgp2DAISYhQCQkJEAk5OUAJWVlgCXl5gAmZmaAJubnACenp8AgaWCAIWghgCDp4QAhqaEAIao + hQCIqoYAiayHAIejiACJpooAiamJAIuqjACMq40Ai6yMAIysjQCZopoAmqiaAJe3lQCetp4AnrybAKOn + nwCgsp4An7egAKGhogClpaYApa2iAKavpACmpqgAqamqAKqqrACtra4AprKmAKiwpQCjvKQApL6kAKm4 + pwCsuakAqr6rALixrgCvr7AAr7uwALGxsQC1t7MAs7O0ALW1tQC7trQAsr+yALy4twC5ubkAvrq5ALu7 + vAC+vb0Awru3AMa6tQDDvLkAxL+9AMi9uQCOzo0AhN6EAJPDkgCSx5EAlMiSAJXRlACd1J0Ant6eAKDf + nwCK4YoAkeSRAJrgmgCiwKAApsKlAKPIowCmyqYAp8OoAKnGqQCpyqoArsqtALLNsQC6w7oAt9G1ALrU + uQDGwL4AysG9AM3BvAC/v8AAwcHBAMXCwgDDw8QAxcXGAMjCwADNxMEAz8fEAMjIxgDHx8gAycnJAM3K + yQDNzMsAzMzMANDFwQDRyMUA1MvHANHNywDUzcoA0s7NANXPzADW0M4A2NHOANXU1ADY09AA2tTRANzW + 0wDa1dQA3djVANrZ2QDf29gA3d3dAODSzQDl1M0A7NfOAOzYzwDi1tEA5tfQAOfZ0wDg2dYA5NrVAOrZ + 0gDs2dEA6dvVAO7b1ADu3dYA4drYAOLd2gDl3tsA6t7YAO/f2ADl4N0A6uDbAO7h2wDp4t0A7uPdAO/k + 3wDw4doA8ePcAPHk3gDj4uEA5OPiAOTk4wDl5eQA6OLgAOrk4ADt5eEA6OfmAOzn5ADu6OQA6urpAO3q + 6QDt7OoA7u7sAPDm4QDx6eUA9OnkAPXs5wDw6+gA8u3qAPXu6QDy7uwA8vDuAPbw7QD48u8A8/HwAPXz + 8QD09PIA+PPwAPj08gAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHlK + QkJCQkJCQkJCQkJCQkJCQkJCQkJDbQAAAAAAAABQbW9iYmJiYmJiYmJiYmJiYmJiYmJiZnilSgAAAAAA + bWANAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ2eUAAAAK5tDQECAgICAgICAgICAgICAgICAgICAgICAg2l + eQAApEYBAQICAgICAgIOJSUlJSUlJSUlJRwlHA8CAn5NAACkHAIEAgQCBAIEAhDg/f39+Pj29vb29vbs + EgIEcUoAAKQcAgQEBAQCBAQEEODw7u7W1tbGxsbGxvYSBAKWUAAApEcEBAQEBAQEBAQQ4Pju7u7W1tbO + xsbG6RIEBHFQAAClRwQEBAQEBgQEBhHg+MSysrKIiIiIiMbsFAQGllAAAKVYBgYdb29qb2pqZOD48PDm + 3Nzczs7OzuwUBgSZZwAArVgGBlTs5tzc1Nyr4PjCvLjmuLS0qqrW7BUGBplnAAClWwYGVezWzMzJybLg + +Obm1Pa08ObctNzsFQYGm2sAAK5bCAZV7NzMyMm6iOD31MK+6br29PC07vYWCAiZbQAArlsICFfs1KmH + hIR24P3cwszpxPb097rw7BsICJttAACuWwgIV+zm5tzc1rTg9+bUwva45vDmuPD2GwgIm20AAK5bCwtV + 7NyppKm6fef4wsLE5r6+usS6+OwnCwubbQAArlsXGGHs6dTm5r6l5vj49vb3+Pb29tTm4CgYGJttAACu + WxgrY/jmvK68wq7s+Pf39/f39/fCh32eKSsYm20AAK1bKy6W7Ozg5uDCuOz99/399/39977CwmYvLiub + bQAApVssM5b46cLCwsK47P399/399/33wrxzMjMzLJtnAAClVy43mf3swtTg8Lzg/f39/f39/f3CczY1 + NTUum2cAAKVVNDqb/fb29vb25sK8vK6upYuNjYs/Ojo6OjeYZwAApVE3PZ347Pbw9vb29vaqpap5PT09 + PT0/PT0/N5hQAACkKjlAn/329vbw9vbw9q7srYlAQEBAQEBAQEA7mEoAAKQqO4qg/fb2+Pj29vj2uK6O + ioqKioqKioqKij2YTQAApUY5kqDg4Obg4ODg4OCuj5KSkpKSkpKSkpKSPJZQAACuahqSlJGRkZGRkZGR + kZSTk5OTk5OTk5OTk5IreXkAAACtRho9QUFBQUFBQUFBQUFBQUFBQUFBQUE7K2BnAAAAAAClZxwdHh4e + HR4dHh0eHR0dHR0dHR0dHUZndwAAAAAAAACupYB5gHmAeYB5gHmAeYB5gHmAeYB7gK0AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////8AAAD+AAAAfAAAADgAAAAYAAAAGAAAABgAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABwAAAA+AAAAfwAAAP/////ygAAAAYAAAAMAAAAAEACAAAAAAAQAIAAAAA + AAAAAAAAAAEAAAABAAAAAAAAL5EvAC+WLwAvmi8AMowyADWLNQAwkTAAMZQxADSSNAAwmjAAMZ4xADSZ + NAA1nzUAMKEwADClMAA1ojUANqY2ADCpMAAwrTAANqk2ADetNgA7rzsAObM5ADyxPABWklYAW5ZaAFuY + WQBcmFoAX5pfAEi4SABNvE0AZ5tlAG6ibABmtmcAabppAG2/bQBRwFEAVsBWAFbFVgBYxlgAXsZeAF3J + XQBizGIAZcxlAGvRawBs0WwAbdVtAHDRbwB11nUAedZ5AH/bfwB+3H4AhKGBAIK0gACRvY8Al6iVAJuh + nACcpJ0AoaGiAKenqACpqaoArq6uAKu7qQCvvq4AsL+uAK+vsACwsLAAsbaxALW1tgC+t7QAvrm3ALe3 + uAC4uLkAvLy9AIPJggCC24IAid+JAJfBlQCH4IcAjeONAJDjkACjyaIArM6rALDArgCl2KQAqdmoALHC + sACyxLEAysC7AM3DvwC/v8AAwcHCAMPDxADFxMUAycLAAMrFwgDPx8MAycbGAM3HxQDIycYAx8fIAMnJ + yADOy8oAy8zIAM3MygDPz88A1cfBANHKxgDVycQA18zHANjLxgDVzswA2c7JAMnXxwDN1ssAy9rKANrQ + ywDa0c0Az8/QANbS0ADV1NIA1tbVANrV0QDc1dEA2tbUANnZ1wDe2NUA3NrZANvc2gDe3NsA3t7dAOXS + ygDl08wA5dXOAOfY0gDi2tYA6NnTAO3Z0QDp3NYA7t3WAOHb2ADi3NoA5N3ZAOXf3ADq39oA4OHfAOfg + 3QDr4NsA6OHeAPDg2QDw4twA4uLhAOnj4ADq5OEA7OXiAO/p5QDv6ugA8ebhAPHq5gDy7eoA9u7qAPPv + 7AD17+wA9vHuAPjy7gD08vEA+PTyAPn29AD6+PYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABJOkE9PT09PT09PT09PT09 + PUI7QgAAAGQ4GQUFBQUFBQUFBQUFBQUFBQUcREkAAEIZAQEBAQEBAQcHBwcHBwcHBwcBHD0AAEcFBwcB + AQEBH2dnZ2dnYWddYTcBB0kAAEILCQEDAwMDIKSdlpWLi4mJiz8LB0kAAEkHCwMDCwMDIKadk4uGhYWF + iz8DB0kAAEkLDRwaHBoZNKaTenVwbmpqi1MNC1oAAEkND2eYmJiYYaaZfo6GdXBullMNDV0AAF0PEGeT + hoaFWKaemZ56np11nVYND10AAF0NFWeTZm5YRaaOb4Z6pKB6nlYSDWcAAF0VEmeZmH6GXaaemZt6np56 + oFYSFWQAAF0VF2eZYWF1RaaZjpiOjn5+pFYXF10AAF0dJXmejo6OZ6ampKCmoKB6eT4kHV0AAF0eKHmb + jn+OZ6ampKampqBdYTUnHl0AAEkkK36cenqOZ6impqampqBkNisrJF0AAEkkL3+cnJygf5F/f39yc3JN + LCwsJF0AAEkpMZGkoJymoKB6ZWFKLzAvMS8wKkkAAEIrS5GcppygnKR5f1FLMzMzMzMzK0gAAEkrTJil + pqWmpaV5UkxOTk5OTk5OK0gAAEghTFVVVVVVVVVUUFBQUFBQUFBMIzwAAHY4IiwuLi4uLiwsLC4sLi4u + LiwiOFsAAAByR0E9PDw8PDxBPTw9PTw9PT1DZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AMAA + AwCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAA + AQCAAAEAgAABAIAAAQCAAAEAgAABAMAAAwD///8AKAAAABAAAAAgAAAAAQAIAAAAAAAAAQAAAAAAAAAA + AAAAAQAAAAEAAAAAAAAwkjAAMJYwADeSNgAwmzAAR5VGAEeZRgBInUcASZVIAFWUUwBWllUAWJtZAEii + RwBJp0gAVqBVAFSvUwBcp1sAW6FcAF2mXQBcq1sAXqtfAGiWaQBynnIAZ6NnAGmqagBqrmsAZLFlAGe0 + ZgBgv2AAbLJsAGy2bABuuW4AeaZ6AHupewByu3MAdb11AHqzegB5tHoAeL14AGTNZAB0wXUAe8F6AHnG + eQB8xnwActVyAH7RfQCcvpsAp6moAKusqwCrr6wAt7q3AIbBhwCByoEAhsmFAIXOhgCF0IQAgN2AAIXZ + hACK0IoAncGcAJHQkQCS35IAnNecAJvemwChw58AjeKNAL3AuwC52rkAx8e/AMnGxgDIycIAyszFAM7O + ygDZycMA28zGANbOygDE08MA1NHPAN3QygDY0s8A39TPANbS0ADZ09AA2tTRANrW1QDe2NYA3dvaAN/d + 2wDj1c4A4NbRAOPZ1QDl2dQA4NvYAOLc2QDk3dkA4d7cAOjf2wDC4sEA5eDeAOjh3gDt4dwA8ePdAPHk + 3wDt5eEA6+bkAO3o5QDy5+IA8ermAPTq5QDx7OkA9e7qAPPw7gD08O0A+PLvAPXy8AD29PEA+PPwAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAADAWFxcXFxcXFxcXFyAvAAAVAQEBAQgKCgoKCgoB + IQAACgECAQIubmxqZmZqCBgAAAsCBAIEO2pZTkpKZAYYAAARDkdHREhsXGBOTmQHHQAAERNnW1hZZ1xi + bFtnDR0AABMTZ1lITW5cXG5cbw0fAAAaG21NWU1uZGdqXG0PKAAAHSttVFZWb3Nzb01CHCsAAB81bVxi + VnNzc3NIKyc1AAAiPHNubmpNR0A3LSwsNQAAIj5zbW9vX0w5OTg4ODoAACU+YWFhYUM9QUFBQUEzAAAy + JSYmJiYmJiYrIiYlMAAAAAAAAAAAAAAAAAAAAAAA//8AAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIAB + AACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAA//8AACgAAAAwAAAAYAAAAAEAIAAAAAAAgCUAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9fX4GeHh5Onp6 + emmAgIF8gYGCf4GBgn+BgYJ/gYGCf4GBgn+BgYJ/gYGCf4GBgn+BgYJ/gYGCf4GBgn+BgYJ/gYGCf4GB + gn+BgYJ/gYGCf4GBgn+BgYJ/gYGCf4GBgn+BgYJ/gYGCf4GBgn+BgYJ/gYGCf4GBgn+BgYJ/gYGCf39/ + gHx4eHlpdnZ3Onp6ewYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhISFBnl5 + enSOjo7klpaX/pKSk/6Ojo7/i4uM/ouLi/+Li4v+i4uM/ouLjP6Li4v/i4uL/ouLi/6Li4v/i4uL/ouL + i/6Li4v/i4uL/ouLi/6Li4z/i4uL/ouLi/6Li4z/i4uM/ouLi/6Li4v/i4uL/ouLjP+Li4z+i4uM/ouL + i/+Li4z+i4uL/oyMjP+Ojo/+jY2O/oWFhuR1dXZ0enp7BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACHh4gVjIyNxqSkpf+ZmZr/wMDB/87Ozv/Pz8//0NDQ/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR + 0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR + 0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0v/Y2Nn/1tbW/62trf+Pj4//fn5/xnh4eRYAAAAAAAAAAAAA + AAAAAAAAAAAAAJOTkwaUlJXGpqan/qSkpf6nrqj/X4tf/j+GP/42iDb/NYk1/jWJNf81iTX+NYk1/jWJ + Nf41iTX/NYk1/jWJNf41iTX/NYk1/jWJNf41iTX/NYk1/jWJNf41iTX/NYk1/jWJNf41iTX/NYk1/jWJ + Nf41iTX/NYk1/jWJNf81iTX+NYk1/jWJNf81iTX+NYk1/jaINv8/hj/+YY1h/rW8tf/U1NT+jIyM/oCA + gMZ9fX4GAAAAAAAAAAAAAAAAAAAAAImJinTFxcX/n5+g/oOXg/41izX/L5Av/i+QL/4wkDD/L5Av/jCQ + MP8vkC/+L5Av/i+QL/4wkDD/L5Av/i+QL/4wkDD/L5Av/i+QL/4wkDD/L5Av/i+QL/4wkDD/L5Av/i+Q + L/4wkDD/L5Av/i+QL/4wkDD/L5Av/jCQMP8vkC/+L5Av/jCQMP8vkC/+L5Av/jCQMP8vkC/+L5Av/jWM + Nf+Po4/+1NTV/pKSk/96ent0AAAAAAAAAAAAAAAAmpqbB7CwsOSnp6j/maCa/zWNNf8wkTD/MJEw/zCR + MP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCR + MP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCR + MP8wkTD/MJEw/zCRMP81jTX/tby1/7Ozs/+Li4zkg4OEBwAAAAAAAAAAl5eYO9PT1P6fn5//XItc/i+S + L/4wkjD/L5Iv/i+SL/4wkjD/L5Iv/jCSMP8vki/+L5Iv/i+SL/4wkjD/L5Iv/i+SL/4wkjD/N5Q3/jmU + Of45lTn/OZQ5/jmUOf45lDn/OZQ5/jmUOf45lDn/OZQ5/jmUOf45lDn/OZQ5/jmUOf85lDn+OZQ5/jmU + Of85lDn+OZQ5/jmUOf80kzT+L5Iv/jCSMP8vki/+YZBi/tra2v+VlZb+gICBOwAAAAAAAAAAnJydatPT + 0/6cnJ3/QItA/i+TL/4wkzD/L5Mv/i+TL/4wkzD/L5Mv/jCTMP8vky/+L5Mv/i+TL/4wkzD/L5Mv/i+T + L/42ljb/i5eI/p6hm/6eoZv/naCa/p2fmf6cn5n/nJ6Y/puemP6bnZf/mp2X/pmclv6ZnJb/mZuV/pib + lf+Ym5X+l5qU/pealP+XmZP+lpmT/pSWkP9rkGn+L5Mv/jCTMP8vky/+QItB/tvb2/+ZmZn+g4OEagAA + AAAAAAAAq6urfc3Nzv+ZmZr/N484/zCVMP8wlTD/MJUw/zCVMP8wlTD/MJUw/zCVMP8wlTD/MJUw/zCV + MP8wlTD/MJUw/zCVMP85mDj/o6ef//n6+f/6+vj/+fn4//n5+P/5+fj/+fn3//n59//5+fj/+fn3//n4 + 9//5+Pf/+fj3//n49//5+Pf/+fn3//n49//5+Pf/+fn3/+nq6f90knL/MJUw/zCVMP8wlTD/OI84/9XV + 1v+YmJn/jIyNfQAAAAAAAAAAr6+wf87Ozv6bm5z/N5E3/i+WL/4wljD/L5Yv/i+WL/4wljD/L5Yv/jCW + MP8vli/+L5Yv/i+WL/4wljD/L5Yv/i+WL/45mjj/o6ig/vn5+P706+b/8+ji/vLm4P7y5d//8ePd/vDi + 2/7w4Nr/79/Y/u/e1/7u3dX/7tzU/u3c0//t29P+7tvT/u3b0//t29P+8eXf/urq6f90knL+L5Yv/jCW + MP8vli/+N5E3/tXV1v+ampv+j4+QfwAAAAAAAAAAsbGyf8/Pz/+dnZ7/N5M4/zCYMP8wmDD/MJgw/zCY + MP8wmDD/MJgw/zCYMP8wmDD/MJgw/zCYMP8wmDD/MJgw/zCYMP85mzj/pKmh//n5+P/06+b/8+fi//Lm + 4P/y5N7/8eLb//Dg2f/w39f/7t3V/+7b1P/t2tL/7dnR/+zYz//s187/7NfO/+zXzv/s187/8OLc/+rq + 6f91k3L/MJgw/zCYMP8wmDD/N5M4/9bW1/+dnZ7/kZGSfwAAAAAAAAAAs7Ozf9DQ0f6fn6D/OJQ4/i+Z + L/4wmTD/L5kv/i+ZL/4wmTD/L5kv/jCZMP8vmS/+L5kv/i+ZL/4wmTD/L5kv/i+ZL/45nDj/pamh/vn5 + +P717en/9Orl/vPp4/7z5+H/8uXf/vHj3f7x4tv/8ODZ/u/e1/7u3NX/7tvT/u3Z0f/s2ND+7NfP/uzX + zv/r1s3+8OLc/urq6f91lHP+L5kv/jCZMP8vmS/+OJQ4/tfX1/+fn6D+lJSVfwAAAAAAAAAAtLS1f9HR + 0v6hoaL/OJY4/i+bL/4wmzD/L5sv/i+bL/4wmzD/L5sv/jCbMP8vmy/+L5sv/i+bL/4wmzD/L5sv/i+b + L/45njj/paqi/vn6+f727+v/9ezn/ufe2v7l29f/5NrV/uLX0/7i1tH/4dTP/uDTzf7f0cz/39DK/t7O + yP/dzcf+3czG/t/Nxv/s187+8OPd/urq6v91lHP+L5sv/jCbMP8vmy/+OJY4/tjY2P+hoaP+lpaXfwAA + AAAAAAAAtra2f9LS0/6jo6T/OJg4/i+dL/4wnTD/L50v/jGdMf4xnjH/MZ4x/jGeMf8xnjH+MZ4x/jGe + Mf4xnjH/MZ4x/jGeMf46oDr/pqqi/vn6+P738O3/8erm/s3Gw/7MxMH/y8PA/sjAvf7Hv7v/xr26/sa8 + uf7Fu7f/xbq2/sO5tf/CuLP+wrey/sO3sv/r18/+8ePd/urq6v92lXP+L50v/jCdMP8vnS/+OJg4/tnZ + 2f+kpKX+mJiZfwAAAAAAAAAAt7e4f9PT1P+lpaf/OZo5/zCfMP8wnzD/OKA3/4CTff+IlIX/iJSE/4eT + hP+Gk4P/hpOD/4WSgv+EkYH/hJGB/4SQgP+GkYL/qqem//n6+f/38e3/9u/r//Dp5f/u5+P/7ubh/+3k + 3//s497/6+Hc/+vf2v/q3tj/6dzW/+ja1P/o2dP/59fR/+jX0P/t29P/8eXf/+rr6v92lnT/MJ8w/zCf + MP8wnzD/OZo5/9nZ2v+mpqf/mpqbfwAAAAAAAAAAuLi5f9TU1f6np6j/Opw6/jCgMP4xoDH/PKI8/qOk + oP7r7Ov/6+vq/uvr6v/r6+r+6+vq/uvr6v7r6+r/6uvq/urr6v7n5+b/sa6u/vn6+P738e3/9u/r/vLr + 6P7x6ub/8enl/vDo5P716+f/8+nk/u7k3/7u4t3/7ODb/uzf2f/r3df+6tvV/uvb1P/u3dX+8ubg/urr + 6v93l3T+MKAw/jGgMf8woDD+Opw6/tra2/+oqKn+nJydfwAAAAAAAAAAubm6f9XV1v6pqar/Op06/jCi + MP4xojH/PaM8/qSmov7v7+3/6uLd/urg2//p3tr+6N3Y/ujc1v7n29X/5trU/ubZ0v7j1c//sq2s/vn6 + +P738e3/8uvn/s/Jx/7Nx8X/zcfE/sjCv/7o4d3/39jU/szFwv7Lw8D/x7+8/se+uv/Gvbn+xby4/sa8 + uP/u3tf+8uji/urr6v93mHT+MKIw/jGiMf8wojD+Op06/tvb2/+qqqv+np6ffwAAAAAAAAAAurq7f9bW + 1/+rq6z/Op86/zGkMf8xpDH/PaU8/6Wmov/v7+3/6uDb/+nd1//o29b/59nU/+fY0v/m19D/5dXO/+TT + zP/h0Mn/sq6t//n6+f/38e3/9e/r/+Xe2//j3Nn/49zZ/+Ha1//z7Oj/3dfT/9jSzv/u5uL/7eTg/+3j + 3v/s4tz/6t7Z/8W8uP/u4Nr/8+nl/+rr6v93mXX/MaQx/zGkMf8xpDH/Op86/9vb3P+srK3/n5+hfwAA + AAAAAAAAu7u8f9fX2P6srK7/OqE7/jCmMP4xpjH/Pac8/qano/7v7+3/6+Ld/urf2v/p3tj+6dzX/uja + 1f7n2dP/5tfR/uXWz/7i08v/sq6t/vn6+f738e3/9u/r/vbv6/738Oz/9u/r/vbv6/738Oz/3dfU/tvV + 0f727ur/9e3p/vXs5//06uX+8ufi/sa+uv/v493+9Ovn/urr6v94mnX+MKYw/jGmMf8wpjD+OqE7/tzc + 3P+tra/+oaGifwAAAAAAAAAAvLy9f9jY2P6tra//O6M7/jCoMP4xqDH/Pak8/qaopP7v7+7/7OTg/uvi + 3f/i2dT+4NfS/t/V0P7e087/3tHN/t3Qy/7azcf/s6+u/vr6+f738e3/9O3p/tXPzf7Tzcr/0szJ/s/I + xv7t5uL/3tfV/tvV0v738Oz/9+/r/vbu6v/27ej+8+nl/si/vP/x5uH+9e3p/uvr6v94m3b+MKgw/jGo + Mf8wqDD+O6M7/tzc3f+vr7D+oqKjfwAAAAAAAAAAvb2+f9jY2f+urrD/O6U7/zGqMf8xqjH/Pas8/6eo + pP/v7+7/7ebi/+Xd2f/Cvbr/wry5/8C6t/++uLT/vbaz/721sf+8tLD/sa2s//n6+f/38e3/9O3p/9rT + 0f/X0c7/1tDO/9PNyv/v6OT/3dfU/9vV0v/38Oz/9/Ds//fv6//27+v/9Ozn/8jBvv/y6OP/9u/r/+vr + 6v95nHb/Maox/zGqMf8xqjH/O6U7/93d3f+wsLH/o6OlfwAAAAAAAAAAvb2+f9jY2f6vr7H/O6c7/jCs + MP4xrDH/Pa08/qiopP7v7+7/7ebi/uzk4P/f2dX+3tfT/t3W0v7c1ND/29PO/tvRzP7Yzsn/s7Cv/vn6 + +f738e3/9u/r/vbv6/738Oz/9u/r/vbv6/738Oz/3dfU/tvV0v738Oz/9u/r/vfw7P/38Oz+9O3p/sjC + v//z6ub+9/Ht/uvr6v95nXb+MKww/jGsMf8wrDD+O6c7/t3d3f+wsLL+pKSlfwAAAAAAAAAAvr6+f9nZ + 2f6wsLH/O6g7/jCuMP4xrjH/Pa49/qippf7v7+7/7ebi/u3m4v/s5eH+6+Tg/uvj3/7q4t7/6+Ld/urg + 2/7m29b/tbGw/vn6+f738e3/9e7q/uDa1/7e2NX/3tfV/tzV0v7x6ub/3dfU/tfRz/7r5eH/6uTg/urk + 4P/r5OD+6eLf/sjCv//z7Oj+9/Lv/uvr6v96nnf+MK4w/jGuMf8wrjD+O6g7/t3d3f+xsbP+pKSmfwAA + AAAAAAAAvr6+f9nZ2f+wsLH/O6o8/zGwMf8xsDH/PbA9/6mppf/v7+7/7ebi/+fg3P/Gwb//xcC+/8S/ + vf/AvLn/49vX/9TNyv/Dvbr/s6+v//n6+f/38e3/8+zo/9HLyf/Pycf/zsjG/8rEwf/q5OD/4tzZ/8/J + x//OyMb/y8XC/8rEwv/LxML/ysTB/83Gw//17ur/+PPw/+vr6v96n3j/MbAx/zGwMf8xsDH/O6o8/93d + 3f+xsbP/paWmfwAAAAAAAAAAvr6+f9nZ2f6vr7H/Pq0+/kG3Qf49tj3/RrVG/qusqP7v7+7/7ebi/urj + 3//Uzsv+083K/tLNyv7Qy8j/6OHd/s/Kxv7MxsP/tbGx/vn6+f738e3/9u/r/vXu6v717ur/9O7q/vTt + 6v738Oz/9u/r/vTu6v707er/9O3p/vTt6f/07en+8uvn/vHr5//z7Oj+9PDt/urq6f9+onz+P7c//kK4 + Qv9GuUb+P60//t3d3f+xsbL+pKSmfwAAAAAAAAAAvb2+f9jY2f6vr7D/P68//k6+Tv5Ovk7/Wb5Z/ra2 + sv7x8fD/7+nm/u/p5f/v6OX+7+jl/u7o5P7u6OT/7ujk/tPOy/7Uz8z/u7e3/vr6+f738u7/9/Dt/vfw + 7f738O3/9/Dt/vfw7f738e3/9/Dt/vfx7f738e3/9/Ht/vfx7f/07uv+7Obj/ubg3f/l39z+5+Ph/uLi + 4f9+n3z+Tr5O/k6+Tv9Ovk7+QK9B/t3d3f+wsLL+o6OlfwAAAAAAAAAAvb2+f9jY2f+urq//QLFA/1LB + Uv9SwVL/XcFd/7i4tf/y8vH/8Orn/+3n5P/Y09H/19LQ/9bRz//U0M3/6+Xi/9fT0f/Z1NL/wr+///v7 + +v/48/D/+PLv//jy7//48u//+PLv//jy7//48u//+PLv//jy7//48u//+PLv//jy7//x7On/0s3L/8bB + v//FwL7/yMXE/8rJyP+Bon//UsFS/1LBUv9SwVL/QbFB/9zc3f+vr7D/o6OkfwAAAAAAAAAAvLy9f9fX + 2P6tra7/QLJA/lfEV/5XxFf/YcRh/rq7t/7y8vH/8Ovn/uvm4//Szsz+0c3L/tHMy/7Oy8j/6eTh/tjU + 0f7Z1dP/xMHA/vv7+v749PD/+PLv/vjy7/748+//+PLv/vjy7/748+//+PLv/vjy7/748+//+PLv/vjy + 7//s5uP+s6+v/sjGx//FxMT+v729/qqmpv97sXn+V8RX/lfEV/9XxFf+QrNC/tzc3f+urq/+oaGjfwAA + AAAAAAAAu7u8f9bW1/6rq63/QLRB/lvHW/5bx1v/Zcdl/ry9uf7y8vH/8evo/vDr6P/w6uf+8Orn/vDq + 5/7w6uf/8Orn/tnV0/7a1tT/xsPC/vv7+v759PH/+PLv/vjy7/758/D/+PLv/vjy7/758/D/+PLv/vjy + 7/758/D/+PLv/vjy7//s5+T+vbq6/urq6v/g39/+vry8/oawhP9cx1z+W8db/lvHW/9bx1v+QrRC/tvb + 3P+srK7+oKChfwAAAAAAAAAAurq7f9bW1v+qqqv/QbVB/1/KX/9fyl//acpp/76/u//y8/H/8ezp/+/q + 5//j39z/497b/+Ld2//h3dr/7+nm/9rW1P/a1tT/x8XE//v7+v/59PH/+fPw//nz8P/58/D/+fPw//nz + 8P/58/D/+fPw//nz8P/58/D/+fPw//jz7//t6OX/vru7/+Hh4f/BwL//i7OJ/2HKYf9fyl//X8pf/1/K + X/9fyl//Q7ZD/9vb2/+qqqz/np6gfwAAAAAAAAAAubm6f9XV1f6oqKn/QbdB/mTNZP5kzWT/bc1t/sDB + vv7z8/L/8ezp/uzn5P/Szs3+0s7N/tHOzP7Oy8j/6eTh/t3Z1/7Rzsz/x8XE/vv7+v769/X/+vf0/vr3 + 9P769/T/+vf0/vr39P769/T/+vf0/vr39P769/T/+vf0/vr39P/w7ev+vbu7/sXDw/+RtY/+Zsxm/mTN + ZP9kzWT+ZM1k/mTNZP9kzWT+Q7hE/tra2/+oqKr+nZ2efwAAAAAAAAAAt7e4f9TU1P+mpqf/QbhC/2nQ + af9p0Gn/ctBy/8LDwP/z8/L/8u3q//Hs6f/u6eb/7ejm/+3o5f/t6OX/8ezp//Dr6P/r5uT/ycbG//Hx + 8P/y8vH/8fHx//Hx8f/x8fH/8fHx//Hx8P/x8vH/8fHw//Hx8P/x8fD/8fHw//Hx8P/q6un/t7Sz/5q6 + mP9qz2r/adBp/2nQaf9p0Gn/adBp/2nQaf9p0Gn/RLlF/9ra2v+np6j/m5ucfwAAAAAAAAAAtra3f9LS + 0/6kpKX/QrpC/m3Tbf5t023/dtJ2/sTGwv7z9PP/8u3q/vLt6v/x7er+8u3q/vLt6v7y7er/8e3q/vHt + 6v7w7On/0s7N/s3Kyf7Oysn/zMnH/snGxf7HxMP/x8PC/sfExP7FwsL/rLWp/qbCo/6mw6T/psOk/qXB + o/+jwKH+mcSX/nHScf9t023+bdNt/m3Tbf9t023+bdNt/m3Tbf9t023+RbtF/tnZ2f+kpKb+mZmafwAA + AAAAAAAAtbW1f9HR0v6ioqP/Q7tD/nPVc/5z1XP/e9V7/sfIxf709PT/8+7r/vPu6//z7uv+8+7r/vPu + 6/7z7uv/8+7r/vPu6/7z7uv/8+7r/vPu6/7z7ev/7ejm/tnV0/7RzMr/0MvK/tTR0P7R0ND/kLWP/nPV + c/5z1XP/c9Vz/nPVc/9z1XP+c9Vz/nPVc/9z1XP+c9Vz/nPVc/9z1XP+c9Vz/nPVc/9z1XP+RrxG/tjY + 2P+ioqP+l5eYfwAAAAAAAAAAs7O0f9DQ0f+goKH/Q7xD/3fYd/932Hf/gNd//8nKxv/09fT/8+7s//Pu + 7P/z7uv/8+7s//Pu7P/z7uz/8+7r//Pu6//z7uz/8+7r//Pu6//z7uv/5eHf/7u5uf/GxMT/xMLC/8G/ + v/+1srL/ksKR/3fYd/932Hf/d9h3/3fYd/932Hf/d9h3/3fYd/932Hf/d9h3/3fYd/932Hf/d9h3/3fY + d/932Hf/R71H/9fX2P+goKH/lJSWfwAAAAAAAAAAsrKyf8/P0P6dnZ7/Q75D/nzafP582nz/hNqE/svM + yf709fT/8+/s/vPv7P/z7uz+8+/s/vPv7P7z7+z/8+7s/vPu7P7z7+z/8+7s/vPu7P7z7uz/5eHf/sfG + xv7o6Oj/4eHh/sjHxv6ewJ3/fdl9/nzafP582nz/fNp8/nzafP982nz+fNp8/nzafP982nz+fNp8/nza + fP982nz+fNp8/nzafP982nz+SL9I/tbW1/+dnZ7+kpKTfwAAAAAAAAAAsLCxf87Oz/6bm5z/RL9E/oDd + gP6B3YH/iNyI/s3Oy/719fT/9PDt/vTv7f/z7+z+9O/t/vTv7f707+3/8+/s/vPv7P707+3/8+/s/vPv + 7P7z7+3/5+Lg/snHx/7i4uL/y8rK/qTCov6C3IL/gN2A/oDdgP6B3YH/gN2A/oHdgf+A3YD+gN2A/oHd + gf+A3YD+gN2A/oHdgf+A3YD+gN2A/oHdgf+A3YD+ScFJ/tXV1f+bm5z+kJCRfwAAAAAAAAAArKytfdHR + 0f+ZmZr/RL9E/4TfhP+F34X/jN6M/8/Qzf/19vX/9fLv//Xx7//18e//9fHv//Xx7//18e//9fHv//Xx + 7//18e//9fHv//Xx7//08e//6ebl/8jGxv/Ozc3/qcOn/4fdh/+F34X/hd+F/4Xfhf+F34X/hd+F/4Xf + hf+F34X/hd+F/4Xfhf+F34X/hd+F/4Xfhf+F34X/hd+F/4Xfhf+F34X/SMBI/9PT1P+ampz/jY2OfQAA + AAAAAAAAnp6fatvb2/6YmJn/RbVG/oXghf6J4Yn/keCQ/tDRzv7z9PP/8/Pz/vP08//z8/P+8/Tz/vPz + 8/7z8/P/8/Pz/vPz8/7z8/P/8/Pz/vPz8/7z8/P/6urq/sLAwP6vx63/i9+L/onhif6J4Yn/ieGJ/onh + if6J4Yn/ieGJ/onhif+J4Yn+ieGJ/onhif+J4Yn+ieGJ/onhif+J4Yn+ieGJ/onhif+F4IX+R7ZH/tLS + 0v+cnJ3+hYWGagAAAAAAAAAAm5ubO9vb2/6cnJz/XKVc/nDbcP6O447/kuKS/r7PvP7Cz8D/ws/A/sLP + wP/Cz8D+ws/A/sLOv/7Bzr//wc6//sHNv/7Bzb//wM2+/sDNvv6/zL3/vcq7/rPOsf6R4pH/juOO/o7j + jv6O447/juOO/o7jjv6O447/juOO/o7jjv+O447+juOO/o7jjv+O447+juOO/o7jjv+O447+juOO/o7j + jv9s2mz+Yaph/sbGxv+enp/+hISFOwAAAAAAAAAAoKCgB7GxsuS3t7f/iJSJ/0XGRf+K44r/kuSS/5Lk + kv+T5JP/k+ST/5Pkk/+T5JP/k+ST/5Pkk/+T5JP/k+ST/5Pkk/+T5JP/k+ST/5Pkk/+T5JP/k+ST/5Lk + kv+S5JL/kuSS/5Lkkv+S5JL/kuSS/5Lkkv+S5JL/kuSS/5Lkkv+S5JL/kuSS/5Lkkv+S5JL/kuSS/5Lk + kv+S5JL/kuSS/4Xhhf9AxUD/qLSo/6Cgof+UlJXkioqKBwAAAAAAAAAAAAAAAI+PkHTg4OD/kpKS/naV + dv5Fx0b/dd51/pHkkf6V5pX/luaW/pbmlv+W5pb+luaW/pbmlv6W5pb/luaW/pbmlv6W5pb/luaW/pbm + lv6W5pb/luaW/pbmlv6W5pb/luaW/pbmlv6W5pb/luaW/pbmlv6W5pb/luaW/pbmlv+W5pb+luaW/pbm + lv+W5pb+luaW/pXmlf+P5I/+cN1w/kDGQP+EpIX+pqan/qenqP9/f4B0AAAAAAAAAAAAAAAAAAAAAKCg + oAaenp/G1tbX/pCQkf6GkYf/WqNb/kS2Rf5Fw0X/RcRF/kXERf9FxEX+RcRF/kXERf5FxEX/RcRF/kXE + Rf5FxEX/RcRF/kXERf5FxEX/RcRF/kXERf5FxEX/RcRF/kXERf5FxEX/RcRF/kXERf5FxEX/RcRF/kXE + Rf9FxEX+RcRF/kXERf9FxEX+RcRF/kXDRf9EtkT+XKRd/pijmf+enp/+p6eo/o+Pj8aKiosGAAAAAAAA + AAAAAAAAAAAAAAAAAACampoVnZ2dxd/f3/+zs7T/lJSV/4+PkP+Ojo//jo6P/46Oj/+Ojo//jo6P/46O + j/+Ojo//jo6P/46Oj/+Ojo//jo6P/46Oj/+Ojo//jo6P/46Oj/+Ojo//jo6P/46Oj/+Ojo//jo6P/46O + j/+Ojo//jo6P/46Oj/+Ojo//jo6P/46Oj/+Ojo//jo6P/4+PkP+UlJX/mJiZ/6Ojo//Dw8T/k5OUxYmJ + ihUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAn5+fBoyMjHSurq7k19fY/tjY2P7MzMz/x8fH/sbG + x//Gxsf+xsbH/sbGx/7Gxsf/xsbH/sbGx/7Gxsf/xsbH/sbGx/7Gxsf/xsbH/sbGx/7Gxsf/xsbH/sbG + x/7Gxsf/xsbH/sbGx/7Gxsf/xsbH/sbGx//Gxsf+xsbH/sbGx//Gxsf+xsbH/sjIyP/Pz9D+0NDQ/qys + rOOHh4d0lZWVBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgoKAGl5eXOpaW + l2ihoaJ8pKSkf6SkpH+kpKR/pKSkf6SkpH+kpKR/pKSkf6SkpH+kpKR/pKSkf6SkpH+kpKR/pKSkf6Sk + pH+kpKR/pKSkf6SkpH+kpKR/pKSkf6SkpH+kpKR/pKSkf6SkpH+kpKR/pKSkf6SkpH+kpKR/pKSkf6Gh + oXyVlZZolpaWOp6engYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////8AAPwA + AAAAPwAA8AAAAAAPAADgAAAAAAcAAMAAAAAAAwAAwAAAAAADAACAAAAAAAEAAIAAAAAAAQAAgAAAAAAB + AACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAA + AAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAAB + AACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAA + AAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAAB + AACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAADAAAAAAAMAAMAAAAAAAwAA4AAAAAAHAADwAAAAAA8AAPwA + AAAAPwAA////////AAAoAAAAIAAAAEAAAAABACAAAAAAAIAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAB9fX02ioqKqoaGh+mHh4f9hoaH/4aGh/+Ghof/hoaH/4aGh/+Ghof/hoaH/4aG + h/+Ghof/hoaH/4aGh/+Ghof/hoaH/4aGh/+Ghof/hoaH/4aGh/+Ghof/hoaG/YODg+mCgoOqd3d4NgAA + AAAAAAAAAAAAAAAAAAAAAAAAjIyNap2dnvytra7/prKm/561nv+ftp//n7ef/5+3n/+ft5//n7ef/5+3 + n/+ft5//n7ef/5+3n/+ft5//n7ef/5+3n/+ft5//n7ef/5+3n/+ft5//n7ef/5+3n/+ft6D/r7uw/8HB + wf+VlZX8e3t8agAAAAAAAAAAAAAAAI+Pjzavr6/8maKa/0SLRP8wjzD/MI8w/zCPMP8wjzD/MI8w/zCP + MP8wjzD/MI8w/zCPMP8wjzD/MI8w/zCPMP8wjzD/MI8w/zCPMP8wjzD/MI8w/zCPMP8wjzD/MI8w/zCP + MP8wjzD/RYxG/7rDuv+Xl5j8fHx9NgAAAAAAAAAAr6+vq6enqP9EjET/MJEw/zCRMP8wkTD/MJEw/zCR + MP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCR + MP8wkTD/MJEw/zCRMP8wkTD/Ro5G/8XFxf+JiYqrAAAAAAAAAAC5ubnph5SH/zCTMP8wkzD/MJMw/zCT + MP8wkzD/MJMw/zCTMP8wkzD/MJMw/0aWRf99m3v/f559/3+dfP9+nHz/fpx7/32be/98mnr/fJp6/3ya + ef97mXn/e5l5/3qYeP95l3f/TJJL/zCTMP8wkzD/sr+y/42NjukAAAAAAAAAALu7vP57lHz/MJUw/zCV + MP8wlTD/MJUw/zCVMP8wlTD/MJUw/zCVMP8wlTD/VZlU/+Pi4f/49fP/9/Tx//fz8P/38u//9/Lv//bx + 7v/28O3/9fDt//bw7f/28O3/9vDt/+7u7P9dk1z/MJUw/zCVMP+jvKT/k5OU/gAAAAAAAAAAvb2+/32X + fv8wlzD/MJcw/zCXMP8wlzD/MJcw/zCXMP8wlzD/MJcw/zCXMP9Wm1T/4+Ph//Tp5P/y5d//8ePc//Dg + 2f/v3tb/7tvT/+3Z0f/s2M//7NfO/+zXzv/s187/7evp/16UXP8wlzD/MJcw/6S+pP+Xl5j/AAAAAAAA + AAC/v8D/gJqB/zCaMP8wmjD/MJow/zCaMP8wmjD/MJow/zCaMP8wmjD/MJow/1adVf/k4+L/9e3o//Tp + 5P/y5+H/8eTe//Di2//v39j/7t3V/+3a0v/s2ND/7NfO/+zXzv/t6+n/XpZc/zCaMP8wmjD/pb+l/5qa + m/8AAAAAAAAAAMHBwv+CnYP/MJww/zCcMP8wnTD/MZ0x/zGdMf8xnTH/MZ0x/zGdMf8xnTH/V59W/+Tj + 4//38Oz/29TQ/8/HxP/NxMH/y8K+/8rAvP/Jvrr/yLy4/8a7tv/HurX/7NjQ/+7r6v9emF3/MJww/zCc + MP+mwab/np6f/wAAAAAAAAAAw8PE/4Wghv8wnzD/MJ8w/3Obcf+osKX/p6+l/6avpP+mrqP/pa6j/6Wt + ov+jp5//5OTj//fw7f/07On/8enl//Dn4//v5eD/7uPd/+3g2//r3tj/6tvV/+rZ0v/u29T/7uzq/1+Z + Xf8wnzD/MJ8w/6fDqP+hoaL/AAAAAAAAAADFxcb/h6OI/zGiMf8xojH/hqWE/+7s6v/s5eL/6+Tg/+rj + 3//q4t3/6eDc/9HKxv/k5OP/9/Dt/+Hb2P/X0c//1M7L/+7m4v/Xz8z/1MvH/9HIxP/RxsL/0MXA/+7e + 1//u7Ov/YJte/zGiMf8xojH/qMSp/6Skpf8AAAAAAAAAAMfHx/+Jpor/MaQx/zGkMf+Gp4T/7ero/+ne + 2f/o29b/59nT/+bX0P/l1M3/zsG8/+Xk4//38O3/7ujk/+nj3//o4t7/8uvn/9XPy//x6OT/8Obh/+/k + 3//SyMT/7+Lb/+7t6/9gnV7/MaQx/zGkMf+pxqn/pqao/wAAAAAAAAAAyMjJ/4qoi/8xpzH/Macx/4eo + hf/u6+n/6+Ld/+Ta1f/j19P/4dXQ/+DSzf/Mwbz/5eXk//fw7f/n4N3/39jV/93W0//v6OX/19DO//fv + 6//27un/9ezn/9XMyP/x5uD/7+7s/2CfX/8xpzH/Macx/6rHqv+oqKr/AAAAAAAAAADJycr/i6qM/zGq + Mf8xqjH/iKqG/+7s6v/o4d3/x8K//8bAvf/DvLn/wru3/7ixrv/l5eT/9/Dt/+ni3//i29j/4NnW//Dp + 5f/X0M7/9/Ds//fv6//27+v/1s7L//Pq5f/v7u3/YaFf/zGqMf8xqjH/qsmr/6qqq/8AAAAAAAAAAMrK + yv+Mq43/Ma0x/zGtMf+Iq4b/7uzq/+3m4v/s5eH/6+Pf/+ri3f/q4Nv/0snG/+Xl5P/38O3/7OXi/+bg + 3f/l3tv/8erm/9XPzP/v6OT/7ujk/+/o5P/Uzcr/9O3o/+/v7f9ho1//Ma0x/zGtMf+ryqv/q6ut/wAA + AAAAAAAAysrK/4ysjf8ysTL/MbAx/4msh//u7Or/6eLe/8XAvv/Ev73/yMPA/9vU0P+7trT/5uXk//fw + 7f/j3dr/29XS/9jSz//w6eX/3NbT/9nT0P/Y0c7/2NHO/9jSz//27+v/8O/t/2KlYP8zsTP/NbI1/6vL + q/+rq63/AAAAAAAAAADJycr/jKyN/0a7Rv9MvUz/l7eV//Du7P/u6OT/6+Xh/+vk4f/r5eH/29XS/8jC + wP/n5uX/9/Ht//fw7P/38Oz/9/Ds//fw7f/38Oz/9/Dt//fw7f/z7en/6uTh/+nj4P/n5uX/b6pt/029 + Tf9Hu0f/q8ur/6qqrP8AAAAAAAAAAMjIyf+LrIz/S79L/1PCU/+evJv/8e/u/+3n5P/Uz83/087N/9bS + z//g2tj/z8vJ/+rq6f/48/D/+PLv//jy7//48u//+PLv//jy7//48u//+PLv/+Pe2/++urn/vLi3/7+8 + vP90r3L/U8JT/0y/TP+qy6v/qamq/wAAAAAAAAAAx8fI/4mriv9Qw1D/Wsda/6LAoP/x8O7/8Orn/+ji + 4P/n4t//6eTh/+Hc2f/Rzcv/6+vq//nz8P/48/D/+PPw//jz8P/58/D/+PPw//jz8P/48u//2NPR/93d + 3f/a2tr/oLKe/1/DX/9ax1r/UcNR/6nLqv+np6j/AAAAAAAAAADFxcb/iKqI/1XHVf9hy2H/psOk//Lw + 7//v6eb/3dnW/9zY1v/f29j/4t3b/8/Lyv/s7Ov/+fTx//nz8P/58/D/+fPw//nz8P/58/D/+fPw//nz + 8P/a1tT/1dTU/6m4p/9nx2b/Ycth/2HLYf9WyFb/qcup/6Skpv8AAAAAAAAAAMTExf+FqYb/Wsta/2jP + aP+qx6j/8/Hw//Dr6P/l4N7/5ODd/+bi3//t6OX/2NTS/+jn5v/19PP/9PTz//T08//09PP/9PTz//T0 + 8//09PL/9PTy/9vZ2f+suan/b8tu/2jPaP9oz2j/aM9o/1zMXP+oy6j/oqKj/wAAAAAAAAAAwsLC/4On + hP9gz2D/b9Nv/67Krf/z8vD/8u3q//Lt6v/y7ev/8u3q//Lt6v/s5+X/2tbU/9rV1P/Tz87/zcnI/87L + yv/DwcH/k8OS/5XJk/+UyJL/kseR/3jReP9v02//b9Nv/2/Tb/9v02//Ys9i/6fKp/+enp//AAAAAAAA + AADAwMD/gaWC/2XSZf9213b/ss2x//Tz8f/z7uv/8+7r//Pu6//z7uv/8+7r//Pu6//z7uv/8u3q/8zJ + yP/Gw8P/xMLC/7W3s/9403j/dtd2/3bXdv9213b/dtd2/3bXdv9213b/dtd2/3bXdv9o02j/psqm/5ub + nP8AAAAAAAAAAL6+vv9+o3//a9Zr/33bff+30bX/9PPy//Pv7P/z7+z/8+/s//Pv7P/z7+z/8+/s//Pv + 7P/y7uv/zszL/+Xl5f/Iycb/js6N/33bff99233/fdt9/33bff99233/fdt9/33bff99233/fdt9/27X + bv+lyqX/l5eY/wAAAAAAAAAAvb29/nyhff9v2W//hN6E/7rUuf/19PP/9PHu//Tx7v/08e7/9PHu//Tx + 7v/08e7/9PHu//Pw7v/Qzs3/zc3L/5XRlP+E3oT/hN6E/4TehP+E3oT/hN6E/4TehP+E3oT/hN6E/4Te + hP+E3oT/ctpy/6PIo/+UlJX+AAAAAAAAAAC+vr/phJiF/2nZaf+K4Yr/u9S6/+bl5f/m5eX/5uXl/+bl + 5f/l5eX/5eXk/+Xl5P/l5OT/5eTk/8jIx/+d1J3/iuGK/4rhiv+K4Yr/iuGK/4rhiv+K4Yr/iuGK/4rh + iv+K4Yr/iuGK/4rhiv9o2Wj/qr6r/5GRkekAAAAAAAAAALOzs6unp6f/VrtX/43jjf+a4Zr/oN+f/6Df + n/+g35//n9+f/5/fn/+f35//n9+e/5/fnv+e3p7/m+Ca/5Hkkf+R5JH/keSR/5Hkkf+R5JH/keSR/5Hk + kf+R5JH/keSR/5Hkkf+R5JH/i+OL/1W9Vf+ysrL/kpKSqwAAAAAAAAAAlpaXNsbGx/yEkoT/V7tX/2/d + b/994H3/feB9/33gff994H3/feB9/33gff994H3/feB9/33gff994H3/feB9/33gff994H3/feB9/33g + ff994H3/feB9/33gff994H3/feB9/27dbv9UvFX/mqia/5+foPyFhYU2AAAAAAAAAAAAAAAAnJydacXF + xvyjo6P/fZB+/3SadP9zmnT/c5p0/3OadP9zmnT/c5p0/3OadP9zmnT/c5p0/3OadP9zmnT/c5p0/3Oa + dP9zmnT/c5p0/3OadP9zmnT/c5p0/3OadP90mnT/gZSC/6Ojo/+tra78jY2OaQAAAAAAAAAAAAAAAAAA + AAAAAAAAlZWVNq+vr6q5ubnotbW1/bOztP+zs7T/s7O0/7OztP+zs7T/s7O0/7OztP+zs7T/s7O0/7Oz + tP+zs7T/s7O0/7OztP+zs7T/s7O0/7OztP+zs7T/s7O0/7OztP2zs7PorKysqpCQkTYAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAP/////gAAAHwAAAA4AAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAA + AAGAAAABwAAAA+AAAAf/////KAAAABgAAAAwAAAAAQAgAAAAAABgCQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAGNjYxBsbGw5cHBxP3FxcT9xcXE/cXFxP3FxcT9xcXE/cXFxP3FxcT9xcXE/cXFxP3Fx + cT9xcXE/cXFxP3BwcT9ra2w5Y2NjEAAAAAAAAAAAAAAAAAAAAABubm8Fi4uMj5+foPivr7D/rq6u/q6u + rv+urq7/rq6u/q6urv+urq7/rq6u/66urv6urq7/rq6u/q6urv+urq7/rq6u/q6urv+xsbH/paWm+H9/ + gI9ra2wFAAAAAAAAAACdnZ6Qm6Cc/luVW/41izX+Mowy/jKMMv4yjDL+Mowy/jKMMv4yjDL+Mowy/jKM + Mv4yjDL+Mowy/jKMMv4yjDL+Mowy/jKMMv41izX+X5lf/rG2sf6CgoOQAAAAAHh4eBCysrP4VpJW/jCR + MP8wkTD/L5Ev/jCRMP8wkTD/L5Ev/jGSMf80kzT/NJM0/zSTNP40kzT/NJI0/jSTNP80kjT/NJI0/jSS + NP8zkjP/L5Ev/l+bX/+rq6z4dnZ3EImJiTm1tbb/NpA2/jCUMP8wlDD/L5Qv/jCUMP8wlDD/L5Qv/meb + Zf/Mzcr/y8zJ/8vMyP7Ky8f/ycrH/snKxv/Iysb/yMnF/sjJxf+XqJX/L5Qv/jaRNv+4uLn/g4OEOZWV + lj+1tbb+M5Qz/i+XL/4vly/+L5cv/i+XL/4vly/+L5cv/m6hbP738u/+8+fh/vHj3f7w4Nn+793W/u3b + 0/7t2dH+7dnQ/u/e1/6vvq7+L5cv/jOUM/65ubn+jY2OP5iYmT+4uLn/NJg0/jCaMP8wmjD/L5ov/jCa + MP8wmjD/L5ov/m+jbf/49PH/8efi/+vg2/7q3Nf/6NnT/ubWz//l08z/5dLK/u7d1f+wv67/L5ov/jSY + NP+8vL3/kZGTP5ubnD+8vLz/NJs0/jKeMv9bmVn/XJlb/lyYWv9bmFn/W5dZ/oShgf/49fP/6eLe/9zV + 0f7a0c3/2c7K/tfMx//VycT/1cfB/u/e1/+wwK7/MJ4w/jSbNP+/v8D/lpaXP56enz++vr/+NZ81/jai + Nv7Iycb+6ubj/urk4v7p4+D+6OLe/svGxP749fP+6uTg/t/Y1f7l3dr+49vW/tvRzf7Zzsn+2MvG/vDi + 3P6xwa/+MKEw/jWfNf7CwsP+mpqbP6CgoT/BwcL/NaM1/jemNv/Ky8j/6t/a/ujc1v/n2NL/5dXO/srA + u//49fP/8uvn/+3m4v7w6eb/29XS/vLq5f/x5+L/2tDL/vHm4f+xwrD/MKUw/jWjNv/ExMX/nZ2eP6Ki + oz/Dw8T/NqY2/jepNv/LzMn/6uLe/tHKxv/Px8P/zcO//r63tP/49fP/5t/c/9XOzP7f2db/3NbT/vfv + 6//27ur/3dXR/vPr5v+yw7D/MKkw/jamNv/Gxsf/n5+hP6Ojoz/ExMX/Nqo2/jetNv/LzMn/7Obi/uXe + 2v/k3Nj/49nV/snCwP/49fP/8erm/+rk4P7v6OT/29XS/vHq5v/x6ub/29XR/vXu6/+yxLD/MK0w/jaq + Nv/Hx8j/oaGiP6OjpD/ExMX+O687/jyzPP7Mzcr+6uTg/s3Hxf7KxcL+29XR/r65t/749fP+7OXi/uLb + 2P7o4d7+5+Dd/uDa1/7f2dX+3tjV/vXv7P6zxbL+ObM5/jywPP7Hx8j+oaGiP6Kioz/Dw8T/SLhI/lbA + Vv/U1NL/7+nm/uPd2v/i3Nn/4dvY/svGxf/59vT/9/Hu//fx7v748e7/9/Hu/vfx7v/17+z/2tXT/tbS + 0P+ru6n/UMBQ/km4Sf/Gxsf/oKChP6CgoT/BwcL+TbxN/l7GXv7W19X+7+rm/uHc2v7g29j+497b/s/M + yv769/X++PLv/vjy7/748+/++PLv/vjy7/7y7On+yMbH/snHx/6CtID+WcZZ/k29Tv7ExMX+nZ2fP56e + nz+/v8D/UcFR/mbMZv/Z2df/7+rn/trW1P/Z1dL/5N/d/s7Lyv/6+Pb/+fXy//n18v759fL/+fXy/vn1 + 8v/08O3/yMfG/pG9j/9izGL/Ysxi/lLBUv/CwsP/mpqcP5ycnT+8vL3/VsVW/nDRb//b3Nr/8u3q/u/r + 6P/v6uj/8ezp/t7a2P/f3t3/3tzb/9za2v7c2tr/zdbL/svayv/J18f/l8GV/mzRbP9r0Wv/a9Fr/ljG + WP+/v8D/l5eYP5mZmj+5ubr+XMlc/nnWef7e393+8+7r/vPu6/7z7uv+8+7r/vPu6/7z7uv+2tbU/srH + x/7HxcT+g8mC/nXWdf511nX+ddZ1/nXWdf511nX+ddZ1/l7JXv68vL3+kpKTP5aWlj+1tbb/Yc1h/oLb + gv/g4d//8+/s/vPv7P/z7+z/8+/s/vPv7P/z7+z/19TT/97d3f6jyaL/f9t//n7cfv9+3H7/ftx+/n7c + fv9+3H7/ftx+/mPOY/+5ubr/jo6PP4uLizm3t7j/Zc1l/ovfi//i4uH/9PLx/vTy8f/08vH/9PLx/vTy + 8f/08vH/19bV/6zOq/6I34j/h+CH/ofgh/+H4If/h+CH/ofgh/+H4If/h+CH/mbNZv+3t7j/hYWGOXx8 + fBC4uLj4ZrZn/o/jj/6p2qj+qtqp/qraqf6q2an+qtmp/qrZqf6p2Kj+pdik/pDjkP6Q45D+kOOQ/pDj + kP6Q45D+kOOQ/pDjkP6Q45D+jOOM/m2/bf6mpqf4e3t8EAAAAACrq6yQm6Oc/me2Z/9s0Wz/bdVt/m3V + bf9t1W3/bdVt/m3Vbf9t1W3/bdVt/23Vbf5t1W3/bdVt/m3Vbf9t1W3/bdVt/m3Vbf9r0Wv/abpp/pyk + nf+QkJGQAAAAAAAAAACAgIAFqqqqj7OztPiwsLH/qqqr/qqqq/+qqqv/qqqr/qqqq/+qqqv/qqqr/6qq + q/6qqqv/qqqr/qqqq/+qqqv/qqqr/qqqq/+vr6//rq6u+J2dnY99fX4FAAAAAAAAAAAAAAAAAAAAAIKC + gxCRkZI5m5ucP5ycnD+cnJw/nJycP5ycnD+cnJw/nJycP5ycnD+cnJw/nJycP5ycnD+cnJw/nJycP5ub + nD+SkpI5hISEEAAAAAAAAAAAAAAAAOAABwCAAAEAgAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAQCAAAEA4AAHACgA + AAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAS0tMDXR0dGR5eXp/eXl6f3l5 + en95eXp/eXl6f3l5en95eXp/eXl6f3l5en95eXl/cXFyZExMTA0AAAAAU1NUDZyendhynnL/Z6Nn/2ej + Z/9no2f/Z6Nn/2ejZ/9no2f/Z6Nn/2ejZ/9no2f/Z6Nn/3mmev+YmpnYU1NTDZWVlWVolmn/MJIw/zCS + MP8wkjD/MJIw/0mVSP9Xl1b/V5dW/1aWVf9WlVT/VZVU/1WUU/83kjb/e6l7/4KCg2Wmpqd/VpZW/zCW + MP8wljD/MJYw/zCWMP+cvpv/9e7q//Tq5f/y5+L/8eTf//Hj3f/v6OT/R5VG/2mqav+QkJF/rKysf1ib + Wf8wmzD/MJsw/zCbMP8wmzD/ncGc/+/m4v/g1tH/3dDL/9vMxv/ZycP/7eHc/0eZRv9qrmv/l5eZf6+v + sH9boVz/VqBV/8rMxf/IycL/x8e//8/Oy//x6ub/49zY/+jf2//f1M//3dDK/+7k4P9InUf/bLJs/56e + n3+zs7N/XaZd/1ynW//s5eL/5dnU/+PVzv/Z09D/8erm/+Pd2f/j3dn/8+vn/+PZ1f/v6OX/SKJH/222 + bf+jo6R/tLS1f16rX/9cq1v/7Ojl/9nSz//Wzsr/1dHP//Hq5v/j3dn/493Z//Ps6P/k3dn/8e3q/0mn + SP9tum7/pqanf7W1tX9ksWX/Z7Rm/+3p5v/Y0s//2tTR/9TRz//y7Oj/6OLe/+7o5P/o4d7/493a/+3q + 5/9Ur1P/dMF1/6amqH+zs7R/bLZs/3vBev/w7Or/3tjW/+Db2P/d29r/+PPw//jy7//48u//+PLv/9bS + 0P+9wLv/YL9g/3zGfP+jo6V/sLCxf2+5b/+GyYX/8e7r/+Hc2v/l4N7/393b//f08v/29PH/9vTx//bz + 8f/Nz8r/ecZ5/2TNZP+ByoH/np6gf6ysrX9yu3P/kdCR//Pw7v/y7ev/8u3r/+vm5P/a1tX/ycbG/6HD + n/+F0IT/ftF9/3LVcv9y1XL/hc6G/5iYmX+oqKh/db11/5zXnP/08vD/9PDt//Tw7f/08O3/4d7c/8TT + w/+F2YT/gN2A/4DdgP+A3YD/gN2A/4rQiv+RkZJ/mZmZZXq1e/+b3pv/w+LC/8Piwv/C4sL/wuLB/7na + uf+S35L/juOO/47jjv+O447/juOO/4zijP+GwYf/h4eIZVtbXA2rrqvYerN6/3i9eP94vXj/eL14/3i9 + eP94vXj/eL14/3i9eP94vXj/eL14/3i9eP95tHr/naGe2FxcXA0AAAAAXl5eDZycnWSpqap/qqqqf6qq + qn+qqqp/qqqqf6qqqn+qqqp/qqqqf6qqqn+pqal/m5ubZGBgYA0AAAAAgAEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAAA== + + + \ No newline at end of file diff --git a/Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.Designer.cs b/Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.Designer.cs new file mode 100644 index 000000000..1c4850bc6 --- /dev/null +++ b/Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.Designer.cs @@ -0,0 +1,1561 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4961 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 + +namespace Duplicati.Scheduler.Monitor.SQL { + + + /// + ///Represents a strongly typed in-memory cache of data. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + [global::System.Serializable()] + [global::System.ComponentModel.DesignerCategoryAttribute("code")] + [global::System.ComponentModel.ToolboxItem(true)] + [global::System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedDataSetSchema")] + [global::System.Xml.Serialization.XmlRootAttribute("SQLHistoryDataSet")] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.DataSet")] + public partial class SQLHistoryDataSet : global::System.Data.DataSet { + + private HistoryDataTable tableHistory; + + private global::System.Data.SchemaSerializationMode _schemaSerializationMode = global::System.Data.SchemaSerializationMode.IncludeSchema; + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public SQLHistoryDataSet() { + this.BeginInit(); + this.InitClass(); + global::System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler = new global::System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged); + base.Tables.CollectionChanged += schemaChangedHandler; + base.Relations.CollectionChanged += schemaChangedHandler; + this.EndInit(); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected SQLHistoryDataSet(global::System.Runtime.Serialization.SerializationInfo info, global::System.Runtime.Serialization.StreamingContext context) : + base(info, context, false) { + if ((this.IsBinarySerialized(info, context) == true)) { + this.InitVars(false); + global::System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler1 = new global::System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged); + this.Tables.CollectionChanged += schemaChangedHandler1; + this.Relations.CollectionChanged += schemaChangedHandler1; + return; + } + string strSchema = ((string)(info.GetValue("XmlSchema", typeof(string)))); + if ((this.DetermineSchemaSerializationMode(info, context) == global::System.Data.SchemaSerializationMode.IncludeSchema)) { + global::System.Data.DataSet ds = new global::System.Data.DataSet(); + ds.ReadXmlSchema(new global::System.Xml.XmlTextReader(new global::System.IO.StringReader(strSchema))); + if ((ds.Tables["History"] != null)) { + base.Tables.Add(new HistoryDataTable(ds.Tables["History"])); + } + this.DataSetName = ds.DataSetName; + this.Prefix = ds.Prefix; + this.Namespace = ds.Namespace; + this.Locale = ds.Locale; + this.CaseSensitive = ds.CaseSensitive; + this.EnforceConstraints = ds.EnforceConstraints; + this.Merge(ds, false, global::System.Data.MissingSchemaAction.Add); + this.InitVars(); + } + else { + this.ReadXmlSchema(new global::System.Xml.XmlTextReader(new global::System.IO.StringReader(strSchema))); + } + this.GetSerializationData(info, context); + global::System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler = new global::System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged); + base.Tables.CollectionChanged += schemaChangedHandler; + this.Relations.CollectionChanged += schemaChangedHandler; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Browsable(false)] + [global::System.ComponentModel.DesignerSerializationVisibility(global::System.ComponentModel.DesignerSerializationVisibility.Content)] + public HistoryDataTable History { + get { + return this.tableHistory; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.BrowsableAttribute(true)] + [global::System.ComponentModel.DesignerSerializationVisibilityAttribute(global::System.ComponentModel.DesignerSerializationVisibility.Visible)] + public override global::System.Data.SchemaSerializationMode SchemaSerializationMode { + get { + return this._schemaSerializationMode; + } + set { + this._schemaSerializationMode = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.DesignerSerializationVisibilityAttribute(global::System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public new global::System.Data.DataTableCollection Tables { + get { + return base.Tables; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.DesignerSerializationVisibilityAttribute(global::System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public new global::System.Data.DataRelationCollection Relations { + get { + return base.Relations; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void InitializeDerivedDataSet() { + this.BeginInit(); + this.InitClass(); + this.EndInit(); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public override global::System.Data.DataSet Clone() { + SQLHistoryDataSet cln = ((SQLHistoryDataSet)(base.Clone())); + cln.InitVars(); + cln.SchemaSerializationMode = this.SchemaSerializationMode; + return cln; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override bool ShouldSerializeTables() { + return false; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override bool ShouldSerializeRelations() { + return false; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void ReadXmlSerializable(global::System.Xml.XmlReader reader) { + if ((this.DetermineSchemaSerializationMode(reader) == global::System.Data.SchemaSerializationMode.IncludeSchema)) { + this.Reset(); + global::System.Data.DataSet ds = new global::System.Data.DataSet(); + ds.ReadXml(reader); + if ((ds.Tables["History"] != null)) { + base.Tables.Add(new HistoryDataTable(ds.Tables["History"])); + } + this.DataSetName = ds.DataSetName; + this.Prefix = ds.Prefix; + this.Namespace = ds.Namespace; + this.Locale = ds.Locale; + this.CaseSensitive = ds.CaseSensitive; + this.EnforceConstraints = ds.EnforceConstraints; + this.Merge(ds, false, global::System.Data.MissingSchemaAction.Add); + this.InitVars(); + } + else { + this.ReadXml(reader); + this.InitVars(); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override global::System.Xml.Schema.XmlSchema GetSchemaSerializable() { + global::System.IO.MemoryStream stream = new global::System.IO.MemoryStream(); + this.WriteXmlSchema(new global::System.Xml.XmlTextWriter(stream, null)); + stream.Position = 0; + return global::System.Xml.Schema.XmlSchema.Read(new global::System.Xml.XmlTextReader(stream), null); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal void InitVars() { + this.InitVars(true); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal void InitVars(bool initTable) { + this.tableHistory = ((HistoryDataTable)(base.Tables["History"])); + if ((initTable == true)) { + if ((this.tableHistory != null)) { + this.tableHistory.InitVars(); + } + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + private void InitClass() { + this.DataSetName = "SQLHistoryDataSet"; + this.Prefix = ""; + this.Namespace = "http://tempuri.org/SQLHistoryDataSet.xsd"; + this.EnforceConstraints = true; + this.SchemaSerializationMode = global::System.Data.SchemaSerializationMode.IncludeSchema; + this.tableHistory = new HistoryDataTable(); + base.Tables.Add(this.tableHistory); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + private bool ShouldSerializeHistory() { + return false; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + private void SchemaChanged(object sender, global::System.ComponentModel.CollectionChangeEventArgs e) { + if ((e.Action == global::System.ComponentModel.CollectionChangeAction.Remove)) { + this.InitVars(); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static global::System.Xml.Schema.XmlSchemaComplexType GetTypedDataSetSchema(global::System.Xml.Schema.XmlSchemaSet xs) { + SQLHistoryDataSet ds = new SQLHistoryDataSet(); + global::System.Xml.Schema.XmlSchemaComplexType type = new global::System.Xml.Schema.XmlSchemaComplexType(); + global::System.Xml.Schema.XmlSchemaSequence sequence = new global::System.Xml.Schema.XmlSchemaSequence(); + global::System.Xml.Schema.XmlSchemaAny any = new global::System.Xml.Schema.XmlSchemaAny(); + any.Namespace = ds.Namespace; + sequence.Items.Add(any); + type.Particle = sequence; + global::System.Xml.Schema.XmlSchema dsSchema = ds.GetSchemaSerializable(); + if (xs.Contains(dsSchema.TargetNamespace)) { + global::System.IO.MemoryStream s1 = new global::System.IO.MemoryStream(); + global::System.IO.MemoryStream s2 = new global::System.IO.MemoryStream(); + try { + global::System.Xml.Schema.XmlSchema schema = null; + dsSchema.Write(s1); + for (global::System.Collections.IEnumerator schemas = xs.Schemas(dsSchema.TargetNamespace).GetEnumerator(); schemas.MoveNext(); ) { + schema = ((global::System.Xml.Schema.XmlSchema)(schemas.Current)); + s2.SetLength(0); + schema.Write(s2); + if ((s1.Length == s2.Length)) { + s1.Position = 0; + s2.Position = 0; + for (; ((s1.Position != s1.Length) + && (s1.ReadByte() == s2.ReadByte())); ) { + ; + } + if ((s1.Position == s1.Length)) { + return type; + } + } + } + } + finally { + if ((s1 != null)) { + s1.Close(); + } + if ((s2 != null)) { + s2.Close(); + } + } + } + xs.Add(dsSchema); + return type; + } + + public delegate void HistoryRowChangeEventHandler(object sender, HistoryRowChangeEvent e); + + /// + ///Represents the strongly named DataTable class. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + [global::System.Serializable()] + [global::System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedTableSchema")] + public partial class HistoryDataTable : global::System.Data.TypedTableBase { + + private global::System.Data.DataColumn columnUserName; + + private global::System.Data.DataColumn columnMachineName; + + private global::System.Data.DataColumn columnEntryType; + + private global::System.Data.DataColumn columnModificationDate; + + private global::System.Data.DataColumn columnXmlContent; + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public HistoryDataTable() { + this.TableName = "History"; + this.BeginInit(); + this.InitClass(); + this.EndInit(); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal HistoryDataTable(global::System.Data.DataTable table) { + this.TableName = table.TableName; + if ((table.CaseSensitive != table.DataSet.CaseSensitive)) { + this.CaseSensitive = table.CaseSensitive; + } + if ((table.Locale.ToString() != table.DataSet.Locale.ToString())) { + this.Locale = table.Locale; + } + if ((table.Namespace != table.DataSet.Namespace)) { + this.Namespace = table.Namespace; + } + this.Prefix = table.Prefix; + this.MinimumCapacity = table.MinimumCapacity; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected HistoryDataTable(global::System.Runtime.Serialization.SerializationInfo info, global::System.Runtime.Serialization.StreamingContext context) : + base(info, context) { + this.InitVars(); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn UserNameColumn { + get { + return this.columnUserName; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn MachineNameColumn { + get { + return this.columnMachineName; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn EntryTypeColumn { + get { + return this.columnEntryType; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn ModificationDateColumn { + get { + return this.columnModificationDate; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn XmlContentColumn { + get { + return this.columnXmlContent; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Browsable(false)] + public int Count { + get { + return this.Rows.Count; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public HistoryRow this[int index] { + get { + return ((HistoryRow)(this.Rows[index])); + } + } + + public event HistoryRowChangeEventHandler HistoryRowChanging; + + public event HistoryRowChangeEventHandler HistoryRowChanged; + + public event HistoryRowChangeEventHandler HistoryRowDeleting; + + public event HistoryRowChangeEventHandler HistoryRowDeleted; + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void AddHistoryRow(HistoryRow row) { + this.Rows.Add(row); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public HistoryRow AddHistoryRow(string UserName, string MachineName, string EntryType, System.DateTime ModificationDate, string XmlContent) { + HistoryRow rowHistoryRow = ((HistoryRow)(this.NewRow())); + object[] columnValuesArray = new object[] { + UserName, + MachineName, + EntryType, + ModificationDate, + XmlContent}; + rowHistoryRow.ItemArray = columnValuesArray; + this.Rows.Add(rowHistoryRow); + return rowHistoryRow; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public HistoryRow FindByUserNameMachineNameEntryTypeModificationDate(string UserName, string MachineName, string EntryType, System.DateTime ModificationDate) { + return ((HistoryRow)(this.Rows.Find(new object[] { + UserName, + MachineName, + EntryType, + ModificationDate}))); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public override global::System.Data.DataTable Clone() { + HistoryDataTable cln = ((HistoryDataTable)(base.Clone())); + cln.InitVars(); + return cln; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override global::System.Data.DataTable CreateInstance() { + return new HistoryDataTable(); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal void InitVars() { + this.columnUserName = base.Columns["UserName"]; + this.columnMachineName = base.Columns["MachineName"]; + this.columnEntryType = base.Columns["EntryType"]; + this.columnModificationDate = base.Columns["ModificationDate"]; + this.columnXmlContent = base.Columns["XmlContent"]; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + private void InitClass() { + this.columnUserName = new global::System.Data.DataColumn("UserName", typeof(string), null, global::System.Data.MappingType.Element); + base.Columns.Add(this.columnUserName); + this.columnMachineName = new global::System.Data.DataColumn("MachineName", typeof(string), null, global::System.Data.MappingType.Element); + base.Columns.Add(this.columnMachineName); + this.columnEntryType = new global::System.Data.DataColumn("EntryType", typeof(string), null, global::System.Data.MappingType.Element); + base.Columns.Add(this.columnEntryType); + this.columnModificationDate = new global::System.Data.DataColumn("ModificationDate", typeof(global::System.DateTime), null, global::System.Data.MappingType.Element); + base.Columns.Add(this.columnModificationDate); + this.columnXmlContent = new global::System.Data.DataColumn("XmlContent", typeof(string), null, global::System.Data.MappingType.Element); + base.Columns.Add(this.columnXmlContent); + this.Constraints.Add(new global::System.Data.UniqueConstraint("Constraint1", new global::System.Data.DataColumn[] { + this.columnUserName, + this.columnMachineName, + this.columnEntryType, + this.columnModificationDate}, true)); + this.columnUserName.AllowDBNull = false; + this.columnUserName.MaxLength = 50; + this.columnMachineName.AllowDBNull = false; + this.columnMachineName.MaxLength = 50; + this.columnEntryType.AllowDBNull = false; + this.columnEntryType.MaxLength = 50; + this.columnModificationDate.AllowDBNull = false; + this.columnXmlContent.MaxLength = 2147483647; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public HistoryRow NewHistoryRow() { + return ((HistoryRow)(this.NewRow())); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override global::System.Data.DataRow NewRowFromBuilder(global::System.Data.DataRowBuilder builder) { + return new HistoryRow(builder); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override global::System.Type GetRowType() { + return typeof(HistoryRow); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowChanged(global::System.Data.DataRowChangeEventArgs e) { + base.OnRowChanged(e); + if ((this.HistoryRowChanged != null)) { + this.HistoryRowChanged(this, new HistoryRowChangeEvent(((HistoryRow)(e.Row)), e.Action)); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowChanging(global::System.Data.DataRowChangeEventArgs e) { + base.OnRowChanging(e); + if ((this.HistoryRowChanging != null)) { + this.HistoryRowChanging(this, new HistoryRowChangeEvent(((HistoryRow)(e.Row)), e.Action)); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowDeleted(global::System.Data.DataRowChangeEventArgs e) { + base.OnRowDeleted(e); + if ((this.HistoryRowDeleted != null)) { + this.HistoryRowDeleted(this, new HistoryRowChangeEvent(((HistoryRow)(e.Row)), e.Action)); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowDeleting(global::System.Data.DataRowChangeEventArgs e) { + base.OnRowDeleting(e); + if ((this.HistoryRowDeleting != null)) { + this.HistoryRowDeleting(this, new HistoryRowChangeEvent(((HistoryRow)(e.Row)), e.Action)); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void RemoveHistoryRow(HistoryRow row) { + this.Rows.Remove(row); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static global::System.Xml.Schema.XmlSchemaComplexType GetTypedTableSchema(global::System.Xml.Schema.XmlSchemaSet xs) { + global::System.Xml.Schema.XmlSchemaComplexType type = new global::System.Xml.Schema.XmlSchemaComplexType(); + global::System.Xml.Schema.XmlSchemaSequence sequence = new global::System.Xml.Schema.XmlSchemaSequence(); + SQLHistoryDataSet ds = new SQLHistoryDataSet(); + global::System.Xml.Schema.XmlSchemaAny any1 = new global::System.Xml.Schema.XmlSchemaAny(); + any1.Namespace = "http://www.w3.org/2001/XMLSchema"; + any1.MinOccurs = new decimal(0); + any1.MaxOccurs = decimal.MaxValue; + any1.ProcessContents = global::System.Xml.Schema.XmlSchemaContentProcessing.Lax; + sequence.Items.Add(any1); + global::System.Xml.Schema.XmlSchemaAny any2 = new global::System.Xml.Schema.XmlSchemaAny(); + any2.Namespace = "urn:schemas-microsoft-com:xml-diffgram-v1"; + any2.MinOccurs = new decimal(1); + any2.ProcessContents = global::System.Xml.Schema.XmlSchemaContentProcessing.Lax; + sequence.Items.Add(any2); + global::System.Xml.Schema.XmlSchemaAttribute attribute1 = new global::System.Xml.Schema.XmlSchemaAttribute(); + attribute1.Name = "namespace"; + attribute1.FixedValue = ds.Namespace; + type.Attributes.Add(attribute1); + global::System.Xml.Schema.XmlSchemaAttribute attribute2 = new global::System.Xml.Schema.XmlSchemaAttribute(); + attribute2.Name = "tableTypeName"; + attribute2.FixedValue = "HistoryDataTable"; + type.Attributes.Add(attribute2); + type.Particle = sequence; + global::System.Xml.Schema.XmlSchema dsSchema = ds.GetSchemaSerializable(); + if (xs.Contains(dsSchema.TargetNamespace)) { + global::System.IO.MemoryStream s1 = new global::System.IO.MemoryStream(); + global::System.IO.MemoryStream s2 = new global::System.IO.MemoryStream(); + try { + global::System.Xml.Schema.XmlSchema schema = null; + dsSchema.Write(s1); + for (global::System.Collections.IEnumerator schemas = xs.Schemas(dsSchema.TargetNamespace).GetEnumerator(); schemas.MoveNext(); ) { + schema = ((global::System.Xml.Schema.XmlSchema)(schemas.Current)); + s2.SetLength(0); + schema.Write(s2); + if ((s1.Length == s2.Length)) { + s1.Position = 0; + s2.Position = 0; + for (; ((s1.Position != s1.Length) + && (s1.ReadByte() == s2.ReadByte())); ) { + ; + } + if ((s1.Position == s1.Length)) { + return type; + } + } + } + } + finally { + if ((s1 != null)) { + s1.Close(); + } + if ((s2 != null)) { + s2.Close(); + } + } + } + xs.Add(dsSchema); + return type; + } + } + + /// + ///Represents strongly named DataRow class. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + public partial class HistoryRow : global::System.Data.DataRow { + + private HistoryDataTable tableHistory; + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal HistoryRow(global::System.Data.DataRowBuilder rb) : + base(rb) { + this.tableHistory = ((HistoryDataTable)(this.Table)); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public string UserName { + get { + return ((string)(this[this.tableHistory.UserNameColumn])); + } + set { + this[this.tableHistory.UserNameColumn] = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public string MachineName { + get { + return ((string)(this[this.tableHistory.MachineNameColumn])); + } + set { + this[this.tableHistory.MachineNameColumn] = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public string EntryType { + get { + return ((string)(this[this.tableHistory.EntryTypeColumn])); + } + set { + this[this.tableHistory.EntryTypeColumn] = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.DateTime ModificationDate { + get { + return ((global::System.DateTime)(this[this.tableHistory.ModificationDateColumn])); + } + set { + this[this.tableHistory.ModificationDateColumn] = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public string XmlContent { + get { + try { + return ((string)(this[this.tableHistory.XmlContentColumn])); + } + catch (global::System.InvalidCastException e) { + throw new global::System.Data.StrongTypingException("The value for column \'XmlContent\' in table \'History\' is DBNull.", e); + } + } + set { + this[this.tableHistory.XmlContentColumn] = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsXmlContentNull() { + return this.IsNull(this.tableHistory.XmlContentColumn); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetXmlContentNull() { + this[this.tableHistory.XmlContentColumn] = global::System.Convert.DBNull; + } + } + + /// + ///Row event argument class + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + public class HistoryRowChangeEvent : global::System.EventArgs { + + private HistoryRow eventRow; + + private global::System.Data.DataRowAction eventAction; + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public HistoryRowChangeEvent(HistoryRow row, global::System.Data.DataRowAction action) { + this.eventRow = row; + this.eventAction = action; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public HistoryRow Row { + get { + return this.eventRow; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataRowAction Action { + get { + return this.eventAction; + } + } + } + } +} +namespace Duplicati.Scheduler.Monitor.SQL.SQLHistoryDataSetTableAdapters { + + + /// + ///Represents the connection and commands used to retrieve and save data. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + [global::System.ComponentModel.DesignerCategoryAttribute("code")] + [global::System.ComponentModel.ToolboxItem(true)] + [global::System.ComponentModel.DataObjectAttribute(true)] + [global::System.ComponentModel.DesignerAttribute("Microsoft.VSDesigner.DataSource.Design.TableAdapterDesigner, Microsoft.VSDesigner" + + ", Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")] + public partial class HistoryTableAdapter : global::System.ComponentModel.Component { + + private global::System.Data.SqlClient.SqlDataAdapter _adapter; + + private global::System.Data.SqlClient.SqlConnection _connection; + + private global::System.Data.SqlClient.SqlTransaction _transaction; + + private global::System.Data.SqlClient.SqlCommand[] _commandCollection; + + private bool _clearBeforeFill; + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public HistoryTableAdapter() { + this.ClearBeforeFill = true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected internal global::System.Data.SqlClient.SqlDataAdapter Adapter { + get { + if ((this._adapter == null)) { + this.InitAdapter(); + } + return this._adapter; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal global::System.Data.SqlClient.SqlConnection Connection { + get { + if ((this._connection == null)) { + this.InitConnection(); + } + return this._connection; + } + set { + this._connection = value; + if ((this.Adapter.InsertCommand != null)) { + this.Adapter.InsertCommand.Connection = value; + } + if ((this.Adapter.DeleteCommand != null)) { + this.Adapter.DeleteCommand.Connection = value; + } + if ((this.Adapter.UpdateCommand != null)) { + this.Adapter.UpdateCommand.Connection = value; + } + for (int i = 0; (i < this.CommandCollection.Length); i = (i + 1)) { + if ((this.CommandCollection[i] != null)) { + ((global::System.Data.SqlClient.SqlCommand)(this.CommandCollection[i])).Connection = value; + } + } + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal global::System.Data.SqlClient.SqlTransaction Transaction { + get { + return this._transaction; + } + set { + this._transaction = value; + for (int i = 0; (i < this.CommandCollection.Length); i = (i + 1)) { + this.CommandCollection[i].Transaction = this._transaction; + } + if (((this.Adapter != null) + && (this.Adapter.DeleteCommand != null))) { + this.Adapter.DeleteCommand.Transaction = this._transaction; + } + if (((this.Adapter != null) + && (this.Adapter.InsertCommand != null))) { + this.Adapter.InsertCommand.Transaction = this._transaction; + } + if (((this.Adapter != null) + && (this.Adapter.UpdateCommand != null))) { + this.Adapter.UpdateCommand.Transaction = this._transaction; + } + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected global::System.Data.SqlClient.SqlCommand[] CommandCollection { + get { + if ((this._commandCollection == null)) { + this.InitCommandCollection(); + } + return this._commandCollection; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool ClearBeforeFill { + get { + return this._clearBeforeFill; + } + set { + this._clearBeforeFill = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + private void InitAdapter() { + this._adapter = new global::System.Data.SqlClient.SqlDataAdapter(); + global::System.Data.Common.DataTableMapping tableMapping = new global::System.Data.Common.DataTableMapping(); + tableMapping.SourceTable = "Table"; + tableMapping.DataSetTable = "History"; + tableMapping.ColumnMappings.Add("UserName", "UserName"); + tableMapping.ColumnMappings.Add("MachineName", "MachineName"); + tableMapping.ColumnMappings.Add("EntryType", "EntryType"); + tableMapping.ColumnMappings.Add("ModificationDate", "ModificationDate"); + tableMapping.ColumnMappings.Add("XmlContent", "XmlContent"); + this._adapter.TableMappings.Add(tableMapping); + this._adapter.DeleteCommand = new global::System.Data.SqlClient.SqlCommand(); + this._adapter.DeleteCommand.Connection = this.Connection; + this._adapter.DeleteCommand.CommandText = "DELETE FROM [dbo].[History] WHERE (([UserName] = @Original_UserName) AND ([Machin" + + "eName] = @Original_MachineName) AND ([EntryType] = @Original_EntryType) AND ([Mo" + + "dificationDate] = @Original_ModificationDate))"; + this._adapter.DeleteCommand.CommandType = global::System.Data.CommandType.Text; + this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@Original_UserName", global::System.Data.SqlDbType.VarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "UserName", global::System.Data.DataRowVersion.Original, false, null, "", "", "")); + this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@Original_MachineName", global::System.Data.SqlDbType.VarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "MachineName", global::System.Data.DataRowVersion.Original, false, null, "", "", "")); + this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@Original_EntryType", global::System.Data.SqlDbType.VarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "EntryType", global::System.Data.DataRowVersion.Original, false, null, "", "", "")); + this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@Original_ModificationDate", global::System.Data.SqlDbType.DateTime, 0, global::System.Data.ParameterDirection.Input, 0, 0, "ModificationDate", global::System.Data.DataRowVersion.Original, false, null, "", "", "")); + this._adapter.InsertCommand = new global::System.Data.SqlClient.SqlCommand(); + this._adapter.InsertCommand.Connection = this.Connection; + this._adapter.InsertCommand.CommandText = @"INSERT INTO [dbo].[History] ([UserName], [MachineName], [EntryType], [ModificationDate], [XmlContent]) VALUES (@UserName, @MachineName, @EntryType, @ModificationDate, @XmlContent); +SELECT UserName, MachineName, EntryType, ModificationDate, XmlContent FROM History WHERE (EntryType = @EntryType) AND (MachineName = @MachineName) AND (ModificationDate = @ModificationDate) AND (UserName = @UserName)"; + this._adapter.InsertCommand.CommandType = global::System.Data.CommandType.Text; + this._adapter.InsertCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@UserName", global::System.Data.SqlDbType.VarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "UserName", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._adapter.InsertCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@MachineName", global::System.Data.SqlDbType.VarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "MachineName", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._adapter.InsertCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@EntryType", global::System.Data.SqlDbType.VarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "EntryType", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._adapter.InsertCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@ModificationDate", global::System.Data.SqlDbType.DateTime, 0, global::System.Data.ParameterDirection.Input, 0, 0, "ModificationDate", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._adapter.InsertCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@XmlContent", global::System.Data.SqlDbType.Xml, 0, global::System.Data.ParameterDirection.Input, 0, 0, "XmlContent", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._adapter.UpdateCommand = new global::System.Data.SqlClient.SqlCommand(); + this._adapter.UpdateCommand.Connection = this.Connection; + this._adapter.UpdateCommand.CommandText = @"UPDATE [dbo].[History] SET [UserName] = @UserName, [MachineName] = @MachineName, [EntryType] = @EntryType, [ModificationDate] = @ModificationDate, [XmlContent] = @XmlContent WHERE (([UserName] = @Original_UserName) AND ([MachineName] = @Original_MachineName) AND ([EntryType] = @Original_EntryType) AND ([ModificationDate] = @Original_ModificationDate)); +SELECT UserName, MachineName, EntryType, ModificationDate, XmlContent FROM History WHERE (EntryType = @EntryType) AND (MachineName = @MachineName) AND (ModificationDate = @ModificationDate) AND (UserName = @UserName)"; + this._adapter.UpdateCommand.CommandType = global::System.Data.CommandType.Text; + this._adapter.UpdateCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@UserName", global::System.Data.SqlDbType.VarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "UserName", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._adapter.UpdateCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@MachineName", global::System.Data.SqlDbType.VarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "MachineName", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._adapter.UpdateCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@EntryType", global::System.Data.SqlDbType.VarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "EntryType", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._adapter.UpdateCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@ModificationDate", global::System.Data.SqlDbType.DateTime, 0, global::System.Data.ParameterDirection.Input, 0, 0, "ModificationDate", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._adapter.UpdateCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@XmlContent", global::System.Data.SqlDbType.Xml, 0, global::System.Data.ParameterDirection.Input, 0, 0, "XmlContent", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._adapter.UpdateCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@Original_UserName", global::System.Data.SqlDbType.VarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "UserName", global::System.Data.DataRowVersion.Original, false, null, "", "", "")); + this._adapter.UpdateCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@Original_MachineName", global::System.Data.SqlDbType.VarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "MachineName", global::System.Data.DataRowVersion.Original, false, null, "", "", "")); + this._adapter.UpdateCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@Original_EntryType", global::System.Data.SqlDbType.VarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "EntryType", global::System.Data.DataRowVersion.Original, false, null, "", "", "")); + this._adapter.UpdateCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@Original_ModificationDate", global::System.Data.SqlDbType.DateTime, 0, global::System.Data.ParameterDirection.Input, 0, 0, "ModificationDate", global::System.Data.DataRowVersion.Original, false, null, "", "", "")); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + private void InitConnection() { + this._connection = new global::System.Data.SqlClient.SqlConnection(); + this._connection.ConnectionString = global::Duplicati.Scheduler.Monitor.SQL.Properties.Settings.Default.BackupsConnectionString; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + private void InitCommandCollection() { + this._commandCollection = new global::System.Data.SqlClient.SqlCommand[3]; + this._commandCollection[0] = new global::System.Data.SqlClient.SqlCommand(); + this._commandCollection[0].Connection = this.Connection; + this._commandCollection[0].CommandText = "SELECT UserName, MachineName, EntryType, ModificationDate, XmlContent FROM dbo.Hi" + + "story"; + this._commandCollection[0].CommandType = global::System.Data.CommandType.Text; + this._commandCollection[1] = new global::System.Data.SqlClient.SqlCommand(); + this._commandCollection[1].Connection = this.Connection; + this._commandCollection[1].CommandText = "SELECT UserName, MachineName, EntryType, ModificationDate, XmlContent FROM dbo.Hi" + + "story\r\nWHERE (UserName = @aUserName) AND (MachineName = @aMachineName) AN" + + "D (EntryType = @aEntryType) AND (ModificationDate = @aModificationDate)"; + this._commandCollection[1].CommandType = global::System.Data.CommandType.Text; + this._commandCollection[1].Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@aUserName", global::System.Data.SqlDbType.VarChar, 50, global::System.Data.ParameterDirection.Input, 0, 0, "UserName", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._commandCollection[1].Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@aMachineName", global::System.Data.SqlDbType.VarChar, 50, global::System.Data.ParameterDirection.Input, 0, 0, "MachineName", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._commandCollection[1].Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@aEntryType", global::System.Data.SqlDbType.VarChar, 50, global::System.Data.ParameterDirection.Input, 0, 0, "EntryType", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._commandCollection[1].Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@aModificationDate", global::System.Data.SqlDbType.DateTime, 8, global::System.Data.ParameterDirection.Input, 0, 0, "ModificationDate", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._commandCollection[2] = new global::System.Data.SqlClient.SqlCommand(); + this._commandCollection[2].Connection = this.Connection; + this._commandCollection[2].CommandText = "SELECT MAX(ModificationDate) FROM History\r\nWHERE (UserName = @aUserName) A" + + "ND (MachineName = @aMachineName) AND (EntryType = @aEntryType)"; + this._commandCollection[2].CommandType = global::System.Data.CommandType.Text; + this._commandCollection[2].Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@aUserName", global::System.Data.SqlDbType.VarChar, 50, global::System.Data.ParameterDirection.Input, 0, 0, "UserName", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._commandCollection[2].Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@aMachineName", global::System.Data.SqlDbType.VarChar, 50, global::System.Data.ParameterDirection.Input, 0, 0, "MachineName", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + this._commandCollection[2].Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@aEntryType", global::System.Data.SqlDbType.VarChar, 50, global::System.Data.ParameterDirection.Input, 0, 0, "EntryType", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")] + [global::System.ComponentModel.DataObjectMethodAttribute(global::System.ComponentModel.DataObjectMethodType.Fill, true)] + public virtual int Fill(SQLHistoryDataSet.HistoryDataTable dataTable) { + this.Adapter.SelectCommand = this.CommandCollection[0]; + if ((this.ClearBeforeFill == true)) { + dataTable.Clear(); + } + int returnValue = this.Adapter.Fill(dataTable); + return returnValue; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")] + [global::System.ComponentModel.DataObjectMethodAttribute(global::System.ComponentModel.DataObjectMethodType.Select, true)] + public virtual SQLHistoryDataSet.HistoryDataTable GetData() { + this.Adapter.SelectCommand = this.CommandCollection[0]; + SQLHistoryDataSet.HistoryDataTable dataTable = new SQLHistoryDataSet.HistoryDataTable(); + this.Adapter.Fill(dataTable); + return dataTable; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")] + [global::System.ComponentModel.DataObjectMethodAttribute(global::System.ComponentModel.DataObjectMethodType.Fill, false)] + public virtual int FillBy(SQLHistoryDataSet.HistoryDataTable dataTable, string aUserName, string aMachineName, string aEntryType, System.DateTime aModificationDate) { + this.Adapter.SelectCommand = this.CommandCollection[1]; + if ((aUserName == null)) { + throw new global::System.ArgumentNullException("aUserName"); + } + else { + this.Adapter.SelectCommand.Parameters[0].Value = ((string)(aUserName)); + } + if ((aMachineName == null)) { + throw new global::System.ArgumentNullException("aMachineName"); + } + else { + this.Adapter.SelectCommand.Parameters[1].Value = ((string)(aMachineName)); + } + if ((aEntryType == null)) { + throw new global::System.ArgumentNullException("aEntryType"); + } + else { + this.Adapter.SelectCommand.Parameters[2].Value = ((string)(aEntryType)); + } + this.Adapter.SelectCommand.Parameters[3].Value = ((System.DateTime)(aModificationDate)); + if ((this.ClearBeforeFill == true)) { + dataTable.Clear(); + } + int returnValue = this.Adapter.Fill(dataTable); + return returnValue; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")] + [global::System.ComponentModel.DataObjectMethodAttribute(global::System.ComponentModel.DataObjectMethodType.Select, false)] + public virtual SQLHistoryDataSet.HistoryDataTable GetDataBy(string aUserName, string aMachineName, string aEntryType, System.DateTime aModificationDate) { + this.Adapter.SelectCommand = this.CommandCollection[1]; + if ((aUserName == null)) { + throw new global::System.ArgumentNullException("aUserName"); + } + else { + this.Adapter.SelectCommand.Parameters[0].Value = ((string)(aUserName)); + } + if ((aMachineName == null)) { + throw new global::System.ArgumentNullException("aMachineName"); + } + else { + this.Adapter.SelectCommand.Parameters[1].Value = ((string)(aMachineName)); + } + if ((aEntryType == null)) { + throw new global::System.ArgumentNullException("aEntryType"); + } + else { + this.Adapter.SelectCommand.Parameters[2].Value = ((string)(aEntryType)); + } + this.Adapter.SelectCommand.Parameters[3].Value = ((System.DateTime)(aModificationDate)); + SQLHistoryDataSet.HistoryDataTable dataTable = new SQLHistoryDataSet.HistoryDataTable(); + this.Adapter.Fill(dataTable); + return dataTable; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")] + public virtual int Update(SQLHistoryDataSet.HistoryDataTable dataTable) { + return this.Adapter.Update(dataTable); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")] + public virtual int Update(SQLHistoryDataSet dataSet) { + return this.Adapter.Update(dataSet, "History"); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")] + public virtual int Update(global::System.Data.DataRow dataRow) { + return this.Adapter.Update(new global::System.Data.DataRow[] { + dataRow}); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")] + public virtual int Update(global::System.Data.DataRow[] dataRows) { + return this.Adapter.Update(dataRows); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")] + [global::System.ComponentModel.DataObjectMethodAttribute(global::System.ComponentModel.DataObjectMethodType.Delete, true)] + public virtual int Delete(string Original_UserName, string Original_MachineName, string Original_EntryType, System.DateTime Original_ModificationDate) { + if ((Original_UserName == null)) { + throw new global::System.ArgumentNullException("Original_UserName"); + } + else { + this.Adapter.DeleteCommand.Parameters[0].Value = ((string)(Original_UserName)); + } + if ((Original_MachineName == null)) { + throw new global::System.ArgumentNullException("Original_MachineName"); + } + else { + this.Adapter.DeleteCommand.Parameters[1].Value = ((string)(Original_MachineName)); + } + if ((Original_EntryType == null)) { + throw new global::System.ArgumentNullException("Original_EntryType"); + } + else { + this.Adapter.DeleteCommand.Parameters[2].Value = ((string)(Original_EntryType)); + } + this.Adapter.DeleteCommand.Parameters[3].Value = ((System.DateTime)(Original_ModificationDate)); + global::System.Data.ConnectionState previousConnectionState = this.Adapter.DeleteCommand.Connection.State; + if (((this.Adapter.DeleteCommand.Connection.State & global::System.Data.ConnectionState.Open) + != global::System.Data.ConnectionState.Open)) { + this.Adapter.DeleteCommand.Connection.Open(); + } + try { + int returnValue = this.Adapter.DeleteCommand.ExecuteNonQuery(); + return returnValue; + } + finally { + if ((previousConnectionState == global::System.Data.ConnectionState.Closed)) { + this.Adapter.DeleteCommand.Connection.Close(); + } + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")] + [global::System.ComponentModel.DataObjectMethodAttribute(global::System.ComponentModel.DataObjectMethodType.Insert, true)] + public virtual int Insert(string UserName, string MachineName, string EntryType, System.DateTime ModificationDate, object XmlContent) { + if ((UserName == null)) { + throw new global::System.ArgumentNullException("UserName"); + } + else { + this.Adapter.InsertCommand.Parameters[0].Value = ((string)(UserName)); + } + if ((MachineName == null)) { + throw new global::System.ArgumentNullException("MachineName"); + } + else { + this.Adapter.InsertCommand.Parameters[1].Value = ((string)(MachineName)); + } + if ((EntryType == null)) { + throw new global::System.ArgumentNullException("EntryType"); + } + else { + this.Adapter.InsertCommand.Parameters[2].Value = ((string)(EntryType)); + } + this.Adapter.InsertCommand.Parameters[3].Value = ((System.DateTime)(ModificationDate)); + if ((XmlContent == null)) { + this.Adapter.InsertCommand.Parameters[4].Value = global::System.DBNull.Value; + } + else { + this.Adapter.InsertCommand.Parameters[4].Value = ((object)(XmlContent)); + } + global::System.Data.ConnectionState previousConnectionState = this.Adapter.InsertCommand.Connection.State; + if (((this.Adapter.InsertCommand.Connection.State & global::System.Data.ConnectionState.Open) + != global::System.Data.ConnectionState.Open)) { + this.Adapter.InsertCommand.Connection.Open(); + } + try { + int returnValue = this.Adapter.InsertCommand.ExecuteNonQuery(); + return returnValue; + } + finally { + if ((previousConnectionState == global::System.Data.ConnectionState.Closed)) { + this.Adapter.InsertCommand.Connection.Close(); + } + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")] + [global::System.ComponentModel.DataObjectMethodAttribute(global::System.ComponentModel.DataObjectMethodType.Update, true)] + public virtual int Update(string UserName, string MachineName, string EntryType, System.DateTime ModificationDate, object XmlContent, string Original_UserName, string Original_MachineName, string Original_EntryType, System.DateTime Original_ModificationDate) { + if ((UserName == null)) { + throw new global::System.ArgumentNullException("UserName"); + } + else { + this.Adapter.UpdateCommand.Parameters[0].Value = ((string)(UserName)); + } + if ((MachineName == null)) { + throw new global::System.ArgumentNullException("MachineName"); + } + else { + this.Adapter.UpdateCommand.Parameters[1].Value = ((string)(MachineName)); + } + if ((EntryType == null)) { + throw new global::System.ArgumentNullException("EntryType"); + } + else { + this.Adapter.UpdateCommand.Parameters[2].Value = ((string)(EntryType)); + } + this.Adapter.UpdateCommand.Parameters[3].Value = ((System.DateTime)(ModificationDate)); + if ((XmlContent == null)) { + this.Adapter.UpdateCommand.Parameters[4].Value = global::System.DBNull.Value; + } + else { + this.Adapter.UpdateCommand.Parameters[4].Value = ((object)(XmlContent)); + } + if ((Original_UserName == null)) { + throw new global::System.ArgumentNullException("Original_UserName"); + } + else { + this.Adapter.UpdateCommand.Parameters[5].Value = ((string)(Original_UserName)); + } + if ((Original_MachineName == null)) { + throw new global::System.ArgumentNullException("Original_MachineName"); + } + else { + this.Adapter.UpdateCommand.Parameters[6].Value = ((string)(Original_MachineName)); + } + if ((Original_EntryType == null)) { + throw new global::System.ArgumentNullException("Original_EntryType"); + } + else { + this.Adapter.UpdateCommand.Parameters[7].Value = ((string)(Original_EntryType)); + } + this.Adapter.UpdateCommand.Parameters[8].Value = ((System.DateTime)(Original_ModificationDate)); + global::System.Data.ConnectionState previousConnectionState = this.Adapter.UpdateCommand.Connection.State; + if (((this.Adapter.UpdateCommand.Connection.State & global::System.Data.ConnectionState.Open) + != global::System.Data.ConnectionState.Open)) { + this.Adapter.UpdateCommand.Connection.Open(); + } + try { + int returnValue = this.Adapter.UpdateCommand.ExecuteNonQuery(); + return returnValue; + } + finally { + if ((previousConnectionState == global::System.Data.ConnectionState.Closed)) { + this.Adapter.UpdateCommand.Connection.Close(); + } + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")] + [global::System.ComponentModel.DataObjectMethodAttribute(global::System.ComponentModel.DataObjectMethodType.Update, true)] + public virtual int Update(object XmlContent, string Original_UserName, string Original_MachineName, string Original_EntryType, System.DateTime Original_ModificationDate) { + return this.Update(Original_UserName, Original_MachineName, Original_EntryType, Original_ModificationDate, XmlContent, Original_UserName, Original_MachineName, Original_EntryType, Original_ModificationDate); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")] + public virtual global::System.Nullable LatestQuery(string aUserName, string aMachineName, string aEntryType) { + global::System.Data.SqlClient.SqlCommand command = this.CommandCollection[2]; + if ((aUserName == null)) { + throw new global::System.ArgumentNullException("aUserName"); + } + else { + command.Parameters[0].Value = ((string)(aUserName)); + } + if ((aMachineName == null)) { + throw new global::System.ArgumentNullException("aMachineName"); + } + else { + command.Parameters[1].Value = ((string)(aMachineName)); + } + if ((aEntryType == null)) { + throw new global::System.ArgumentNullException("aEntryType"); + } + else { + command.Parameters[2].Value = ((string)(aEntryType)); + } + global::System.Data.ConnectionState previousConnectionState = command.Connection.State; + if (((command.Connection.State & global::System.Data.ConnectionState.Open) + != global::System.Data.ConnectionState.Open)) { + command.Connection.Open(); + } + object returnValue; + try { + returnValue = command.ExecuteScalar(); + } + finally { + if ((previousConnectionState == global::System.Data.ConnectionState.Closed)) { + command.Connection.Close(); + } + } + if (((returnValue == null) + || (returnValue.GetType() == typeof(global::System.DBNull)))) { + return new global::System.Nullable(); + } + else { + return new global::System.Nullable(((global::System.DateTime)(returnValue))); + } + } + } + + /// + ///TableAdapterManager is used to coordinate TableAdapters in the dataset to enable Hierarchical Update scenarios + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + [global::System.ComponentModel.DesignerCategoryAttribute("code")] + [global::System.ComponentModel.ToolboxItem(true)] + [global::System.ComponentModel.DesignerAttribute("Microsoft.VSDesigner.DataSource.Design.TableAdapterManagerDesigner, Microsoft.VSD" + + "esigner, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapterManager")] + public partial class TableAdapterManager : global::System.ComponentModel.Component { + + private UpdateOrderOption _updateOrder; + + private HistoryTableAdapter _historyTableAdapter; + + private bool _backupDataSetBeforeUpdate; + + private global::System.Data.IDbConnection _connection; + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public UpdateOrderOption UpdateOrder { + get { + return this._updateOrder; + } + set { + this._updateOrder = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.EditorAttribute("Microsoft.VSDesigner.DataSource.Design.TableAdapterManagerPropertyEditor, Microso" + + "ft.VSDesigner, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" + + "", "System.Drawing.Design.UITypeEditor")] + public HistoryTableAdapter HistoryTableAdapter { + get { + return this._historyTableAdapter; + } + set { + this._historyTableAdapter = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool BackupDataSetBeforeUpdate { + get { + return this._backupDataSetBeforeUpdate; + } + set { + this._backupDataSetBeforeUpdate = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Browsable(false)] + public global::System.Data.IDbConnection Connection { + get { + if ((this._connection != null)) { + return this._connection; + } + if (((this._historyTableAdapter != null) + && (this._historyTableAdapter.Connection != null))) { + return this._historyTableAdapter.Connection; + } + return null; + } + set { + this._connection = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Browsable(false)] + public int TableAdapterInstanceCount { + get { + int count = 0; + if ((this._historyTableAdapter != null)) { + count = (count + 1); + } + return count; + } + } + + /// + ///Update rows in top-down order. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + private int UpdateUpdatedRows(SQLHistoryDataSet dataSet, global::System.Collections.Generic.List allChangedRows, global::System.Collections.Generic.List allAddedRows) { + int result = 0; + if ((this._historyTableAdapter != null)) { + global::System.Data.DataRow[] updatedRows = dataSet.History.Select(null, null, global::System.Data.DataViewRowState.ModifiedCurrent); + updatedRows = this.GetRealUpdatedRows(updatedRows, allAddedRows); + if (((updatedRows != null) + && (0 < updatedRows.Length))) { + result = (result + this._historyTableAdapter.Update(updatedRows)); + allChangedRows.AddRange(updatedRows); + } + } + return result; + } + + /// + ///Insert rows in top-down order. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + private int UpdateInsertedRows(SQLHistoryDataSet dataSet, global::System.Collections.Generic.List allAddedRows) { + int result = 0; + if ((this._historyTableAdapter != null)) { + global::System.Data.DataRow[] addedRows = dataSet.History.Select(null, null, global::System.Data.DataViewRowState.Added); + if (((addedRows != null) + && (0 < addedRows.Length))) { + result = (result + this._historyTableAdapter.Update(addedRows)); + allAddedRows.AddRange(addedRows); + } + } + return result; + } + + /// + ///Delete rows in bottom-up order. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + private int UpdateDeletedRows(SQLHistoryDataSet dataSet, global::System.Collections.Generic.List allChangedRows) { + int result = 0; + if ((this._historyTableAdapter != null)) { + global::System.Data.DataRow[] deletedRows = dataSet.History.Select(null, null, global::System.Data.DataViewRowState.Deleted); + if (((deletedRows != null) + && (0 < deletedRows.Length))) { + result = (result + this._historyTableAdapter.Update(deletedRows)); + allChangedRows.AddRange(deletedRows); + } + } + return result; + } + + /// + ///Remove inserted rows that become updated rows after calling TableAdapter.Update(inserted rows) first + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + private global::System.Data.DataRow[] GetRealUpdatedRows(global::System.Data.DataRow[] updatedRows, global::System.Collections.Generic.List allAddedRows) { + if (((updatedRows == null) + || (updatedRows.Length < 1))) { + return updatedRows; + } + if (((allAddedRows == null) + || (allAddedRows.Count < 1))) { + return updatedRows; + } + global::System.Collections.Generic.List realUpdatedRows = new global::System.Collections.Generic.List(); + for (int i = 0; (i < updatedRows.Length); i = (i + 1)) { + global::System.Data.DataRow row = updatedRows[i]; + if ((allAddedRows.Contains(row) == false)) { + realUpdatedRows.Add(row); + } + } + return realUpdatedRows.ToArray(); + } + + /// + ///Update all changes to the dataset. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public virtual int UpdateAll(SQLHistoryDataSet dataSet) { + if ((dataSet == null)) { + throw new global::System.ArgumentNullException("dataSet"); + } + if ((dataSet.HasChanges() == false)) { + return 0; + } + if (((this._historyTableAdapter != null) + && (this.MatchTableAdapterConnection(this._historyTableAdapter.Connection) == false))) { + throw new global::System.ArgumentException("All TableAdapters managed by a TableAdapterManager must use the same connection s" + + "tring."); + } + global::System.Data.IDbConnection workConnection = this.Connection; + if ((workConnection == null)) { + throw new global::System.ApplicationException("TableAdapterManager contains no connection information. Set each TableAdapterMana" + + "ger TableAdapter property to a valid TableAdapter instance."); + } + bool workConnOpened = false; + if (((workConnection.State & global::System.Data.ConnectionState.Broken) + == global::System.Data.ConnectionState.Broken)) { + workConnection.Close(); + } + if ((workConnection.State == global::System.Data.ConnectionState.Closed)) { + workConnection.Open(); + workConnOpened = true; + } + global::System.Data.IDbTransaction workTransaction = workConnection.BeginTransaction(); + if ((workTransaction == null)) { + throw new global::System.ApplicationException("The transaction cannot begin. The current data connection does not support transa" + + "ctions or the current state is not allowing the transaction to begin."); + } + global::System.Collections.Generic.List allChangedRows = new global::System.Collections.Generic.List(); + global::System.Collections.Generic.List allAddedRows = new global::System.Collections.Generic.List(); + global::System.Collections.Generic.List adaptersWithAcceptChangesDuringUpdate = new global::System.Collections.Generic.List(); + global::System.Collections.Generic.Dictionary revertConnections = new global::System.Collections.Generic.Dictionary(); + int result = 0; + global::System.Data.DataSet backupDataSet = null; + if (this.BackupDataSetBeforeUpdate) { + backupDataSet = new global::System.Data.DataSet(); + backupDataSet.Merge(dataSet); + } + try { + // ---- Prepare for update ----------- + // + if ((this._historyTableAdapter != null)) { + revertConnections.Add(this._historyTableAdapter, this._historyTableAdapter.Connection); + this._historyTableAdapter.Connection = ((global::System.Data.SqlClient.SqlConnection)(workConnection)); + this._historyTableAdapter.Transaction = ((global::System.Data.SqlClient.SqlTransaction)(workTransaction)); + if (this._historyTableAdapter.Adapter.AcceptChangesDuringUpdate) { + this._historyTableAdapter.Adapter.AcceptChangesDuringUpdate = false; + adaptersWithAcceptChangesDuringUpdate.Add(this._historyTableAdapter.Adapter); + } + } + // + //---- Perform updates ----------- + // + if ((this.UpdateOrder == UpdateOrderOption.UpdateInsertDelete)) { + result = (result + this.UpdateUpdatedRows(dataSet, allChangedRows, allAddedRows)); + result = (result + this.UpdateInsertedRows(dataSet, allAddedRows)); + } + else { + result = (result + this.UpdateInsertedRows(dataSet, allAddedRows)); + result = (result + this.UpdateUpdatedRows(dataSet, allChangedRows, allAddedRows)); + } + result = (result + this.UpdateDeletedRows(dataSet, allChangedRows)); + // + //---- Commit updates ----------- + // + workTransaction.Commit(); + if ((0 < allAddedRows.Count)) { + global::System.Data.DataRow[] rows = new System.Data.DataRow[allAddedRows.Count]; + allAddedRows.CopyTo(rows); + for (int i = 0; (i < rows.Length); i = (i + 1)) { + global::System.Data.DataRow row = rows[i]; + row.AcceptChanges(); + } + } + if ((0 < allChangedRows.Count)) { + global::System.Data.DataRow[] rows = new System.Data.DataRow[allChangedRows.Count]; + allChangedRows.CopyTo(rows); + for (int i = 0; (i < rows.Length); i = (i + 1)) { + global::System.Data.DataRow row = rows[i]; + row.AcceptChanges(); + } + } + } + catch (global::System.Exception ex) { + workTransaction.Rollback(); + // ---- Restore the dataset ----------- + if (this.BackupDataSetBeforeUpdate) { + global::System.Diagnostics.Debug.Assert((backupDataSet != null)); + dataSet.Clear(); + dataSet.Merge(backupDataSet); + } + else { + if ((0 < allAddedRows.Count)) { + global::System.Data.DataRow[] rows = new System.Data.DataRow[allAddedRows.Count]; + allAddedRows.CopyTo(rows); + for (int i = 0; (i < rows.Length); i = (i + 1)) { + global::System.Data.DataRow row = rows[i]; + row.AcceptChanges(); + row.SetAdded(); + } + } + } + throw ex; + } + finally { + if (workConnOpened) { + workConnection.Close(); + } + if ((this._historyTableAdapter != null)) { + this._historyTableAdapter.Connection = ((global::System.Data.SqlClient.SqlConnection)(revertConnections[this._historyTableAdapter])); + this._historyTableAdapter.Transaction = null; + } + if ((0 < adaptersWithAcceptChangesDuringUpdate.Count)) { + global::System.Data.Common.DataAdapter[] adapters = new System.Data.Common.DataAdapter[adaptersWithAcceptChangesDuringUpdate.Count]; + adaptersWithAcceptChangesDuringUpdate.CopyTo(adapters); + for (int i = 0; (i < adapters.Length); i = (i + 1)) { + global::System.Data.Common.DataAdapter adapter = adapters[i]; + adapter.AcceptChangesDuringUpdate = true; + } + } + } + return result; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected virtual void SortSelfReferenceRows(global::System.Data.DataRow[] rows, global::System.Data.DataRelation relation, bool childFirst) { + global::System.Array.Sort(rows, new SelfReferenceComparer(relation, childFirst)); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected virtual bool MatchTableAdapterConnection(global::System.Data.IDbConnection inputConnection) { + if ((this._connection != null)) { + return true; + } + if (((this.Connection == null) + || (inputConnection == null))) { + return true; + } + if (string.Equals(this.Connection.ConnectionString, inputConnection.ConnectionString, global::System.StringComparison.Ordinal)) { + return true; + } + return false; + } + + /// + ///Update Order Option + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + public enum UpdateOrderOption { + + InsertUpdateDelete = 0, + + UpdateInsertDelete = 1, + } + + /// + ///Used to sort self-referenced table's rows + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + private class SelfReferenceComparer : object, global::System.Collections.Generic.IComparer { + + private global::System.Data.DataRelation _relation; + + private int _childFirst; + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal SelfReferenceComparer(global::System.Data.DataRelation relation, bool childFirst) { + this._relation = relation; + if (childFirst) { + this._childFirst = -1; + } + else { + this._childFirst = 1; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + private bool IsChildAndParent(global::System.Data.DataRow child, global::System.Data.DataRow parent) { + global::System.Diagnostics.Debug.Assert((child != null)); + global::System.Diagnostics.Debug.Assert((parent != null)); + global::System.Data.DataRow newParent = child.GetParentRow(this._relation, global::System.Data.DataRowVersion.Default); + for ( + ; ((newParent != null) + && ((object.ReferenceEquals(newParent, child) == false) + && (object.ReferenceEquals(newParent, parent) == false))); + ) { + newParent = newParent.GetParentRow(this._relation, global::System.Data.DataRowVersion.Default); + } + if ((newParent == null)) { + for (newParent = child.GetParentRow(this._relation, global::System.Data.DataRowVersion.Original); ((newParent != null) + && ((object.ReferenceEquals(newParent, child) == false) + && (object.ReferenceEquals(newParent, parent) == false))); + ) { + newParent = newParent.GetParentRow(this._relation, global::System.Data.DataRowVersion.Original); + } + } + if (object.ReferenceEquals(newParent, parent)) { + return true; + } + return false; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public int Compare(global::System.Data.DataRow row1, global::System.Data.DataRow row2) { + if (object.ReferenceEquals(row1, row2)) { + return 0; + } + if ((row1 == null)) { + return -1; + } + if ((row2 == null)) { + return 1; + } + + // Is row1 the child or grandchild of row2 + if (this.IsChildAndParent(row1, row2)) { + return this._childFirst; + } + + // Is row2 the child or grandchild of row1 + if (this.IsChildAndParent(row2, row1)) { + return (-1 * this._childFirst); + } + return 0; + } + } + } +} + +#pragma warning restore 1591 \ No newline at end of file diff --git a/Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.xsc b/Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.xsc new file mode 100644 index 000000000..551fc56fb --- /dev/null +++ b/Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.xsc @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.xsd b/Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.xsd new file mode 100644 index 000000000..30f8fa5a7 --- /dev/null +++ b/Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.xsd @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + DELETE FROM [dbo].[History] WHERE (([UserName] = @Original_UserName) AND ([MachineName] = @Original_MachineName) AND ([EntryType] = @Original_EntryType) AND ([ModificationDate] = @Original_ModificationDate)) + + + + + + + + + + + INSERT INTO [dbo].[History] ([UserName], [MachineName], [EntryType], [ModificationDate], [XmlContent]) VALUES (@UserName, @MachineName, @EntryType, @ModificationDate, @XmlContent); +SELECT UserName, MachineName, EntryType, ModificationDate, XmlContent FROM History WHERE (EntryType = @EntryType) AND (MachineName = @MachineName) AND (ModificationDate = @ModificationDate) AND (UserName = @UserName) + + + + + + + + + + + + SELECT UserName, MachineName, EntryType, ModificationDate, XmlContent FROM dbo.History + + + + + + UPDATE [dbo].[History] SET [UserName] = @UserName, [MachineName] = @MachineName, [EntryType] = @EntryType, [ModificationDate] = @ModificationDate, [XmlContent] = @XmlContent WHERE (([UserName] = @Original_UserName) AND ([MachineName] = @Original_MachineName) AND ([EntryType] = @Original_EntryType) AND ([ModificationDate] = @Original_ModificationDate)); +SELECT UserName, MachineName, EntryType, ModificationDate, XmlContent FROM History WHERE (EntryType = @EntryType) AND (MachineName = @MachineName) AND (ModificationDate = @ModificationDate) AND (UserName = @UserName) + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT UserName, MachineName, EntryType, ModificationDate, XmlContent FROM dbo.History +WHERE (UserName = @aUserName) AND (MachineName = @aMachineName) AND (EntryType = @aEntryType) AND (ModificationDate = @aModificationDate) + + + + + + + + + + + + + SELECT MAX(ModificationDate) FROM History +WHERE (UserName = @aUserName) AND (MachineName = @aMachineName) AND (EntryType = @aEntryType) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.xss b/Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.xss new file mode 100644 index 000000000..5f282702b --- /dev/null +++ b/Duplicati/Scheduler/Monitor.SQL/SQLHistoryDataSet.xss @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Duplicati/Scheduler/Monitor.SQL/SettingsSupport.cs b/Duplicati/Scheduler/Monitor.SQL/SettingsSupport.cs new file mode 100644 index 000000000..ff2c7992f --- /dev/null +++ b/Duplicati/Scheduler/Monitor.SQL/SettingsSupport.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Duplicati.Scheduler.Monitor.SQL.Properties +{ + internal sealed partial class Settings + { + /// + /// XML that contains encrypted ConnectionString for PhoneHome + /// + public static string MonitorConnection = + Duplicati.Scheduler.Data.HistoryDataSet.GetAppData("SQLMonitorConnection.xml"); + public string BackupsConnectionString + { + get + { + return new Duplicati.Scheduler.Data.ConnectionFromXML( + @"Data Source="+Environment.MachineName+@"\SQLEXPRESS;Initial Catalog=Backups;Integrated Security=True") + .ConnectionString(MonitorConnection); + } + } + } +} diff --git a/Duplicati/Scheduler/Monitor.SQL/app.config b/Duplicati/Scheduler/Monitor.SQL/app.config new file mode 100644 index 000000000..91cd30b4f --- /dev/null +++ b/Duplicati/Scheduler/Monitor.SQL/app.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Duplicati/Scheduler/ShellIcons.cs b/Duplicati/Scheduler/ShellIcons.cs new file mode 100644 index 000000000..e438ff41d --- /dev/null +++ b/Duplicati/Scheduler/ShellIcons.cs @@ -0,0 +1,138 @@ +#region Disclaimer / License +// Copyright (C) 2011, Kenneth Skovhede +// http://www.hexad.dk, opensource@hexad.dk +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +#endregion +using System; +using System.Collections; +using System.Drawing; +using System.Windows.Forms; + +namespace OSGeo.MapGuide.Maestro.ResourceEditors +{ + /// + /// Helper class for Shell Icons + /// + public class ShellIcons + { + private static ImageList m_imageList; + private static Hashtable m_loadedImages; + private static bool m_supported = false; + + static ShellIcons() + { + m_imageList = new ImageList(); + m_loadedImages = new Hashtable(); + m_imageList.ImageSize = new Size(16, 16); + m_imageList.ColorDepth = ColorDepth.Depth32Bit; + //m_imageList.Images.Add(System.Drawing.Image.FromStream(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(typeof(ResourceDataEditor), "blank_icon.gif"))); + m_loadedImages.Add("", 0); + + try + { + //This does nothing on windows, but fails on linux + DestroyIcon(IntPtr.Zero); + m_supported = true; + } + catch + { + m_supported = false; + } + } + + #region Win32 Native Code + [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] + private struct SHFILEINFO + { + public IntPtr hIcon; + public IntPtr iIcon; + [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=260)] + public string szDisplayName; + [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=80)] + public string szTypeName; + } + + [System.Runtime.InteropServices.DllImport("shell32.dll")] + private static extern IntPtr SHGetFileInfo(string pszPath, int dwFileAttributes, ref SHFILEINFO psfi, int cbSizeFileInfo, int uFlags); + + + [System.Runtime.InteropServices.DllImport("User32.dll")] + private static extern int DestroyIcon(IntPtr hIcon); + + private const int SHGFI_ICON = 256; + private const int SHGFI_LARGEICON = 0; + private const int SHGFI_SMALLICON = 1; + private const int SHGFI_USEFILEATTRIBUTES = 16; + private const int SHGFI_OPENICON = 2; + private const int SHGFI_SELECTED = 65536; + + private const int FILE_ATTRIBUTE_NORMAL = 128; + private const int FILE_ATTRIBUTE_DIRECTORY = 16; + + #endregion + + public static bool Supported { get { return m_supported; } } + + public static ImageList ImageList { get { return m_imageList; } } + + public static void AddIcon(string filename, System.Drawing.Image img) + { + string type = System.IO.Path.GetExtension(filename).ToLower(); + if (!m_loadedImages.Contains(type.ToLower())) + { + ShellIcons.ImageList.Images.Add(img); + m_loadedImages.Add(type.ToLower(), ShellIcons.ImageList.Images.Count - 1); + } + } + + public static int GetFolderIcon(bool open) + { + return GetShellIcon("folder", FILE_ATTRIBUTE_DIRECTORY, SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | (open ? SHGFI_OPENICON : 0)); + } + + public static int GetShellIcon(string filename) + { + return GetShellIcon(System.IO.Path.GetExtension(filename).ToLower(), FILE_ATTRIBUTE_NORMAL, SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON); + } + + private static int GetShellIcon(string ext, int type, int attributes) + { + if (!m_loadedImages.Contains(ext) && m_supported) + { + try + { + SHFILEINFO shinfo = new SHFILEINFO(); + SHGetFileInfo(ext, type, ref shinfo, System.Runtime.InteropServices.Marshal.SizeOf(shinfo), attributes); + System.Drawing.Icon tmp = (System.Drawing.Icon)System.Drawing.Icon.FromHandle(shinfo.hIcon).Clone(); + DestroyIcon(shinfo.hIcon); + + m_imageList.Images.Add(tmp); + m_loadedImages.Add(ext, m_imageList.Images.Count - 1); + } + catch + { + } + } + + if (m_loadedImages.ContainsKey(ext)) + return (int)m_loadedImages[ext]; + else + return 0; + } + + } +}