diff --git a/LibreHardwareMonitor/LibreHardwareMonitor.csproj b/LibreHardwareMonitor/LibreHardwareMonitor.csproj
index 2328dd8..f2dd072 100644
--- a/LibreHardwareMonitor/LibreHardwareMonitor.csproj
+++ b/LibreHardwareMonitor/LibreHardwareMonitor.csproj
@@ -77,6 +77,7 @@
+
@@ -87,6 +88,12 @@
Properties\AssemblyVersion.cs
+
+ Form
+
+
+ AuthForm.cs
+
@@ -156,6 +163,9 @@
AboutBox.cs
Designer
+
+ AuthForm.cs
+
PortForm.cs
@@ -299,7 +309,12 @@
-
+
+
+
+
+
+
diff --git a/LibreHardwareMonitor/Resources/Web/favicon.ico b/LibreHardwareMonitor/Resources/Web/favicon.ico
new file mode 100644
index 0000000..0e17037
Binary files /dev/null and b/LibreHardwareMonitor/Resources/Web/favicon.ico differ
diff --git a/LibreHardwareMonitor/Resources/Web/index.html b/LibreHardwareMonitor/Resources/Web/index.html
index 34cbc65..a3337b9 100644
--- a/LibreHardwareMonitor/Resources/Web/index.html
+++ b/LibreHardwareMonitor/Resources/Web/index.html
@@ -5,7 +5,8 @@
- Copyright (C) 2012 Prince Samuel -->
-
+
+
Libre Hardware Monitor - Web Version
@@ -19,19 +20,20 @@
-
+
diff --git a/LibreHardwareMonitor/Resources/ati.png b/LibreHardwareMonitor/Resources/ati.png
new file mode 100644
index 0000000..6ee6ba1
Binary files /dev/null and b/LibreHardwareMonitor/Resources/ati.png differ
diff --git a/LibreHardwareMonitor/UI/AuthForm.Designer.cs b/LibreHardwareMonitor/UI/AuthForm.Designer.cs
new file mode 100644
index 0000000..9a9e873
--- /dev/null
+++ b/LibreHardwareMonitor/UI/AuthForm.Designer.cs
@@ -0,0 +1,186 @@
+namespace LibreHardwareMonitor.UI
+{
+ partial class AuthForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AuthForm));
+ this.enableHTTPAuthCheckBox = new System.Windows.Forms.CheckBox();
+ this.httpAuthUsernameTextBox = new System.Windows.Forms.TextBox();
+ this.httpAuthPasswordTextBox = new System.Windows.Forms.TextBox();
+ this.httpUsernameLabel = new System.Windows.Forms.Label();
+ this.httpPasswordLabel = new System.Windows.Forms.Label();
+ this.credentialsGroupBox = new System.Windows.Forms.GroupBox();
+ this.httpAuthCancelButton = new System.Windows.Forms.Button();
+ this.httpAuthOkButton = new System.Windows.Forms.Button();
+ this.label1 = new System.Windows.Forms.Label();
+ this.label2 = new System.Windows.Forms.Label();
+ this.credentialsGroupBox.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // enableHTTPAuthCheckBox
+ //
+ this.enableHTTPAuthCheckBox.AutoSize = true;
+ this.enableHTTPAuthCheckBox.Location = new System.Drawing.Point(12, 12);
+ this.enableHTTPAuthCheckBox.Name = "enableHTTPAuthCheckBox";
+ this.enableHTTPAuthCheckBox.Size = new System.Drawing.Size(191, 17);
+ this.enableHTTPAuthCheckBox.TabIndex = 0;
+ this.enableHTTPAuthCheckBox.Text = "Enable HTTP Basic Authentication";
+ this.enableHTTPAuthCheckBox.UseVisualStyleBackColor = true;
+ this.enableHTTPAuthCheckBox.CheckedChanged += new System.EventHandler(this.EnableHTTPAuthCheckBox_CheckedChanged);
+ //
+ // httpAuthUsernameTextBox
+ //
+ this.httpAuthUsernameTextBox.Location = new System.Drawing.Point(102, 23);
+ this.httpAuthUsernameTextBox.MaxLength = 255;
+ this.httpAuthUsernameTextBox.Name = "httpAuthUsernameTextBox";
+ this.httpAuthUsernameTextBox.Size = new System.Drawing.Size(171, 20);
+ this.httpAuthUsernameTextBox.TabIndex = 1;
+ //
+ // httpAuthPasswordTextBox
+ //
+ this.httpAuthPasswordTextBox.Location = new System.Drawing.Point(102, 60);
+ this.httpAuthPasswordTextBox.MaxLength = 255;
+ this.httpAuthPasswordTextBox.Name = "httpAuthPasswordTextBox";
+ this.httpAuthPasswordTextBox.PasswordChar = '*';
+ this.httpAuthPasswordTextBox.Size = new System.Drawing.Size(171, 20);
+ this.httpAuthPasswordTextBox.TabIndex = 2;
+ this.httpAuthPasswordTextBox.UseSystemPasswordChar = true;
+ //
+ // httpUsernameLabel
+ //
+ this.httpUsernameLabel.AutoSize = true;
+ this.httpUsernameLabel.Location = new System.Drawing.Point(6, 26);
+ this.httpUsernameLabel.Name = "httpUsernameLabel";
+ this.httpUsernameLabel.Size = new System.Drawing.Size(90, 13);
+ this.httpUsernameLabel.TabIndex = 6;
+ this.httpUsernameLabel.Text = "HTTP UserName:";
+ //
+ // httpPasswordLabel
+ //
+ this.httpPasswordLabel.AutoSize = true;
+ this.httpPasswordLabel.Location = new System.Drawing.Point(6, 63);
+ this.httpPasswordLabel.Name = "httpPasswordLabel";
+ this.httpPasswordLabel.Size = new System.Drawing.Size(88, 13);
+ this.httpPasswordLabel.TabIndex = 7;
+ this.httpPasswordLabel.Text = "HTTP Password:";
+ //
+ // credentialsGroupBox
+ //
+ this.credentialsGroupBox.Controls.Add(this.httpAuthUsernameTextBox);
+ this.credentialsGroupBox.Controls.Add(this.httpPasswordLabel);
+ this.credentialsGroupBox.Controls.Add(this.httpAuthPasswordTextBox);
+ this.credentialsGroupBox.Controls.Add(this.httpUsernameLabel);
+ this.credentialsGroupBox.Location = new System.Drawing.Point(12, 35);
+ this.credentialsGroupBox.Name = "credentialsGroupBox";
+ this.credentialsGroupBox.Size = new System.Drawing.Size(279, 100);
+ this.credentialsGroupBox.TabIndex = 5;
+ this.credentialsGroupBox.TabStop = false;
+ this.credentialsGroupBox.Text = "Credentials";
+ //
+ // httpAuthCancelButton
+ //
+ this.httpAuthCancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.httpAuthCancelButton.Location = new System.Drawing.Point(76, 206);
+ this.httpAuthCancelButton.Name = "httpAuthCancelButton";
+ this.httpAuthCancelButton.Size = new System.Drawing.Size(75, 23);
+ this.httpAuthCancelButton.TabIndex = 3;
+ this.httpAuthCancelButton.Text = "Cancel";
+ this.httpAuthCancelButton.UseVisualStyleBackColor = true;
+ this.httpAuthCancelButton.Click += new System.EventHandler(this.HttpAuthCancelButton_Click);
+ //
+ // httpAuthOkButton
+ //
+ this.httpAuthOkButton.Location = new System.Drawing.Point(157, 206);
+ this.httpAuthOkButton.Name = "httpAuthOkButton";
+ this.httpAuthOkButton.Size = new System.Drawing.Size(75, 23);
+ this.httpAuthOkButton.TabIndex = 4;
+ this.httpAuthOkButton.Text = "OK";
+ this.httpAuthOkButton.UseVisualStyleBackColor = true;
+ this.httpAuthOkButton.Click += new System.EventHandler(this.HttpAuthOkButton_Click);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(12, 138);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(269, 26);
+ this.label1.TabIndex = 8;
+ this.label1.Text = "Password is stored hashed, if you forget it you will need \r\nto set a new one.";
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(12, 174);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(284, 26);
+ this.label2.TabIndex = 9;
+ this.label2.Text = "If the web server is running then it will need to be restarted \r\nfor the change t" +
+ "o take effect.";
+ //
+ // AuthForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.CancelButton = this.httpAuthCancelButton;
+ this.ClientSize = new System.Drawing.Size(305, 241);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.httpAuthOkButton);
+ this.Controls.Add(this.httpAuthCancelButton);
+ this.Controls.Add(this.credentialsGroupBox);
+ this.Controls.Add(this.enableHTTPAuthCheckBox);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "AuthForm";
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Set HTTP Credentials";
+ this.Load += new System.EventHandler(this.AuthForm_Load);
+ this.credentialsGroupBox.ResumeLayout(false);
+ this.credentialsGroupBox.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.CheckBox enableHTTPAuthCheckBox;
+ private System.Windows.Forms.TextBox httpAuthUsernameTextBox;
+ private System.Windows.Forms.TextBox httpAuthPasswordTextBox;
+ private System.Windows.Forms.Label httpUsernameLabel;
+ private System.Windows.Forms.Label httpPasswordLabel;
+ private System.Windows.Forms.GroupBox credentialsGroupBox;
+ private System.Windows.Forms.Button httpAuthCancelButton;
+ private System.Windows.Forms.Button httpAuthOkButton;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Label label2;
+ }
+}
\ No newline at end of file
diff --git a/LibreHardwareMonitor/UI/AuthForm.cs b/LibreHardwareMonitor/UI/AuthForm.cs
new file mode 100644
index 0000000..ffc9b12
--- /dev/null
+++ b/LibreHardwareMonitor/UI/AuthForm.cs
@@ -0,0 +1,47 @@
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// Copyright (C) LibreHardwareMonitor and Contributors.
+// Partial Copyright (C) Michael Möller and Contributors.
+// All Rights Reserved.
+
+using System;
+using System.Windows.Forms;
+
+namespace LibreHardwareMonitor.UI
+{
+ public partial class AuthForm : Form
+ {
+ private readonly MainForm _parent;
+
+ public AuthForm(MainForm m)
+ {
+ InitializeComponent();
+ _parent = m;
+ }
+
+ private void AuthForm_Load(object sender, EventArgs e)
+ {
+ httpAuthUsernameTextBox.Enabled = httpAuthPasswordTextBox.Enabled = enableHTTPAuthCheckBox.Checked = _parent.Server.AuthEnabled;
+ httpAuthUsernameTextBox.Text = _parent.Server.UserName;
+ }
+
+ private void HttpAuthCancelButton_Click(object sender, EventArgs e)
+ {
+ Close();
+ }
+
+ private void HttpAuthOkButton_Click(object sender, EventArgs e)
+ {
+ _parent.Server.UserName = httpAuthUsernameTextBox.Text;
+ _parent.Server.Password = httpAuthPasswordTextBox.Text;
+ _parent.Server.AuthEnabled = enableHTTPAuthCheckBox.Checked;
+ _parent.AuthWebServerMenuItemChecked = _parent.Server.AuthEnabled;
+ Close();
+ }
+
+ private void EnableHTTPAuthCheckBox_CheckedChanged(object sender, EventArgs e)
+ {
+ httpAuthUsernameTextBox.Enabled = httpAuthPasswordTextBox.Enabled = enableHTTPAuthCheckBox.Checked;
+ }
+ }
+}
diff --git a/LibreHardwareMonitor/UI/AuthForm.resx b/LibreHardwareMonitor/UI/AuthForm.resx
new file mode 100644
index 0000000..b7102bd
--- /dev/null
+++ b/LibreHardwareMonitor/UI/AuthForm.resx
@@ -0,0 +1,377 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ AAABAAMAEBAAAAEAIABoBAAANgAAACAgAAABACAAqBAAAJ4EAAAwMAAAAQAgAKglAABGFQAAKAAAABAA
+ AAAgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEU8OykuDgdIIxQSURwdHU8ZGhpPFhYWTxQU
+ FE8SEhJPDxAPTw0KCk8KBQRPCAQDTwcDAU8HAQBPBgQEUQUFBTxLVVb/L215/zdXXP89Ozv/ODc3/zM0
+ M/8vLy//Kioq/yYlJf8iJif/Gycp/xggI/8UHiD/Eh4g/w4SE/8GBARRQWRr/xGXtP8yUln/NDIx/y4u
+ Lf8qKir/KSgo/ycnJ/8lJCP/Iikq/xs4Pf8aOD7/GzpB/xo4Pf8SGhv/BwMDT01aXP46Ulj+Pzc0/kdH
+ R/5MTU3+Q0ND/jw8PP43Nzf+Ly8v/igoKP4lKCn+Iico/hwiI/4cHyD/FBMU/wYHBk9XVVX+Rj8+/klJ
+ Sf6ioqL+rq+u/p+fn/6YmJj+j4+P/oSEhP56enr+dXJy/mNgYP4iHx7+Gxka/xUVFf8HBwdPW1pa/kVF
+ RP5YWFj+rq6u/r6+vv6wsK/+qamp/qCgoP6UlJT+iYmJ/oGBgf5xcXH+JCQk/hsbG/8WFhb/BwcHT15e
+ Xv5ISEj+Wlpa/rW1tf7Gxsb+tra2/qysq/6hoaL+lpaW/oyMjP6EhIT+cnJy/iQkJP4cHBz/GBgY/wcH
+ B09jY2P+TUxM/l5eXv7AwMD+0dHR/r6+vv6vr6/+o6Ok/pmYmf6Rk5P+iouK/nd4d/4lJSX+HR0d/xkZ
+ Gf8HBwdPZ2dn/lBQUP5iYmL+ysrK/tzc3P7Hxsf+tbS1/qmpqf6fn5/+mJiY/o6Pj/57e3z+JSUm/h4e
+ Hv8aGhr/CAgIT2tra/5TU1P+ZGRk/tLS0v7j5eP+zMzM/ry8vP6wsLD+pqam/pubm/6TkZH+f39//igo
+ KP4fHx7/HBwc/wkJCk9ubm7+VlVW/mZlZv7X1tf+6Ojo/tPS0/7Hx8f+urq6/qurq/6dnp7+lJSU/oGB
+ gP4sLCz+Hx4e/x4dHP8LCwtPb29v/lZWVv5nZ2j+4eHh/vLx8v7Z2dn+zc3N/sDAwP6wsrL+pKOk/pmZ
+ mf6Ghob+MDAw/h8gH/8eHx//DQsNT29vb/5YWFj+WVpa/sHBwf7V1dX+wMC//rW1tP6pqan+m5ub/o6P
+ jv6FhYX+cXFx/i4qKv4gLC7/Hiot/w4JB09vb3D+Wlla/lJSUf5VVVX+YGBg/ltbWv5VVVP+Tk5O/kdH
+ R/5BQUH+Ozs6/jAvL/4oKCj+Izk9/x8tL/8QCQhRbm5u/lVVVf5SUlL+S0tL/kRERP5BQUH+PT09/jk5
+ Of41NTX+MzIy/i8vLv4sKSj+Jy4v/h9DTP8iLjH/Ew0KSHp7ev5qamr+ZWVl/mFhYv5cXFz+WFhY/lNS
+ U/5NTU3+R0ZH/kJCQv49PDz+NzU1/jAxMf4qMTL/Jigp/x4cHCn//wAAAAEAAAABAAAAAQAAAAEAAAAB
+ AAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAKAAAACAAAABAAAAAAQAgAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMBBwcHAwYGBgQGBgYEBgYGBAYG
+ BgQGBgYEBgYGBAYGBgQGBgYEBgYGBAYGBgQGBgYEBgYGBAYGBgQGBgYEBgYGBAYGBgQGBgYEBgYGBAYG
+ BgQGBgYEBgYGBAYGBgQGBgYEBwcHAwUFBQIAAAAAAAAAAAAAAAAAAAAAAAAAAAoKCgkMDAwgDQ0NKg0N
+ DSoNDQ0qDQ0NKg0NDSoNDQ0qDQ0NKg0NDSoNDQ0qDQ0NKg0NDSoNDQ0qDQ0NKg0NDSoNDQ0qDQ0NKg0N
+ DSoNDQ0qDQ0NKg0NDSoNDQ0qDQ0NKg0NDSoMDAwlCgoKEQUFBQIAAAAAAAAAAAAAAAAAAAAACAgIFAoK
+ CkcMDAxbDAwMXAwMDFwMDAxcDAwMXAwNDFwNDQ1cDQ0NXA0NDVwNDQ1cDQ0NXA0NDVwNDQ5cDg4OXA4O
+ DlwODg5cDg4OXA4ODlwODg5cDg4OXA4ODlwODg5cDg4OWw0NDVIMDAwlBwcHAwAAAAAAAAAAAAAAAGFh
+ YY9ZWFjFUVBP0kpJSdhIR0fYQkJC2D0+Ptg5OTnZODc22TMyM9kuLi/ZKysr2SYmJtkjIyPZICAf2Rsb
+ G9kXFxjZExMT2Q8ODtkNDAzZDQwM2A0MDNgNDAzYDQ0N2A0NDdgODQ27Dg4OWw0NDSoGBgYEAAAAAAAA
+ AAAAAAAAYmFhvzxCQ/82Uln/NlJZ/zdPVP89PDz/PDw8/zo6Ov85OTn/ODg4/zY2Nv80NDT/NDQ0/zIy
+ Mv8xMTD/Ly4w/yw1OP8qNjj/JzQ1/yYyNP8kMDL/Ii4w/x8sLv8fKy3/HyIi/w0NDdgODg5cDQ0NKgYG
+ BgQAAAAAAAAAAAAAAABjY2K/OFRa/xqXsv8bk6v/M11l/z49Pf89PT3/Ozs7/zo6Of83Nzj/NTY1/zQ0
+ NP8zMzP/MTEw/y8vL/8uLi7/KzQ2/yk1Nv8nMjT/JjAz/yQvMf8jLjD/ISwu/x8rLf8fISL/DQ0N2A4O
+ DlwNDQ0qBgYGBAAAAAAAAAAAAAAAAGZkZL86V13/GpKs/zJkbv9BPz//Pj8+/zw8PP85OTn/Njc2/zQ0
+ Nf8zMjP/MjIy/zAwMP8vLy//Li4u/y0sLP8qKSn/I0hQ/yJHUP8hRk//IEZO/yBGTv8fRU3/HztB/yAf
+ H/8NDQ3YDg4OXA0NDSoGBgYEAAAAAAAAAAAAAAAAaWdovz5WW/83YWr/RkND/0FAQP89PT3/ODc3/zIy
+ Mf8uLi7/LCws/ysrK/8pKSn/Kioq/ygoKP8nJyf/JSUl/yUkJP8kIyP/IyEh/yMiIv8kIiL/JCMj/yQj
+ I/8iISH/ISAg/w0NDdgODg5cDQ0NKgYGBgQAAAAAAAAAAAAAAABqamq/SUhI/0hHR/9GRkb/QUFB/0ZH
+ Rv9/f4D/gICA/3h4eP9xcXH/a2tr/2RkZP9dXV7/V1dX/09PT/9ISEj/Q0NC/0BAQP9AQED/Ozs7/yYm
+ Jv8jIyP/JCQk/yMjI/8jIyH/DQ0N2A4ODlwNDQ0qBgYGBAAAAAAAAAAAAAAAAG5ubr9LS0v/SkpL/0hI
+ SP9BQUH/i4uL/6ysrP+hoqH/n5+e/52bnf+YmJj/lJSU/5CQj/+Li4v/hYaF/4CAgP97e3r/dXR1/3Fx
+ cf9ra2v/Ozs7/yEhIv8kJCT/JCQk/yQkI/8NDQ3YDg4OXA0NDSoGBgYEAAAAAAAAAAAAAAAAcHBwv01N
+ Tf9MTU3/SUpK/0BAP/+Wlpj/q6ur/6inp/+kpKT/oKGg/52cnP+YmJj/k5OT/46Ojv+IiYj/g4OC/319
+ ff93d3f/cXFx/3Fxcf8/Pz//ISEh/yQkJP8lJSX/JSQk/w0NDdkODg5cDQ0NKgYGBgQAAAAAAAAAAAAA
+ AABycnO/T05P/05PT/9MTEz/QUFB/5ubmv+ysrL/rq6u/6urq/+np6f/oqKi/52dnf+ZmZn/k5OT/42O
+ jv+IiIf/gYGB/3x7fP90dXT/cXFx/z8/P/8hISH/JCQl/yUlJf8lJib/DQ0N2Q4ODlwNDQ0qBgYGBAAA
+ AAAAAAAAAAAAAHR1db9RUVH/UFBQ/01NTf9CQkL/np6e/7i4uP+0s7T/sbGx/62trf+oqKj/o6Oj/52d
+ nf+Yl5f/kZKR/4yMi/+FhYX/fn9//3h4eP9zc3P/Pz8//yIiIv8lJSX/JiYm/yYmJv8NDQ3ZDg4OXA0N
+ DSoGBgYEAAAAAAAAAAAAAAAAdnZ2v1RUVP9TU1P/T09P/0VFRf+kpKT/v7+//7u7u/+2trb/sbGx/6mp
+ qf+jo6P/nZ2d/5eXl/+QkZH/jo2N/4mJif+CgoL/fHx8/3d3d/9AQED/IiIi/yYmJv8nJyf/Jycn/w0N
+ DdkODg5cDQ0NKgYGBgQAAAAAAAAAAAAAAAB4eHi/V1dW/1VVVf9QUFD/RkZG/6moqf/Gxsb/wcHB/7y8
+ vP+2trb/q6ys/6Wlpf+fn5//mZiY/5WUlf+RkpL/jI2M/4WFhf9/fn//enp6/0FBQf8iIiP/JiYm/ygn
+ KP8oJyf/DQ0N2Q4ODlwNDQ0qBgYGBAAAAAAAAAAAAAAAAHp6er9YWVn/V1dX/1JSU/9ISEj/ra2t/8zM
+ zP/Gxsb/wcHB/7u7u/+wsLD/qamp/6Ojo/+cnZ3/lpaW/5OTk/+Pj47/iIiI/4CBgP98fH3/QkJC/yMj
+ I/8nJyf/KCgo/ygoKP8ODg7ZDg4OXA0NDSoGBgYEAAAAAAAAAAAAAAAAfXx9v1tbW/9ZWVn/VFVV/0hJ
+ Sf+xsbH/0tLS/8vLy//FxcX/v7++/7Ozs/+qqqr/pKWk/6Cfn/+ampr/mpia/5GRkf+Li4r/goOD/35+
+ fv9CQ0P/IyQk/ycnJ/8pKSn/KSkp/xAQENkODg5cDQ0NKgYGBgQAAAAAAAAAAAAAAAB+fn6/XV1d/1tb
+ W/9WVlb/S0lJ/7Oysv/W1tb/z8/P/8nJyf/CwsL/tbW1/66trf+np6f/oqKi/5ycnP+ZmJn/k5OT/4yM
+ jP+FhYX/f39//0ZFRv8kJCT/KCgo/ykpKf8pKSn/EhIS2Q4ODlwNDQ0qBgYGBAAAAAAAAAAAAAAAAIGB
+ gb9eXl7/XFxc/1dYV/9KSkr/tLS0/9rb2v/S0tL/zczM/8XFxf+/v7//uLi4/7Gxsf+rq6r/o6Oj/5yc
+ nP+UlZT/jY2N/4aFhv+AgID/SUlI/yMjI/8oKCj/KSkp/ykpKf8UFBTZDg4OXA0NDSoGBgYEAAAAAAAA
+ AAAAAAAAg4ODv19fX/9eXl7/WVhZ/0tLS/+0tLT/3d3d/9TU1P/Ozs7/x8bH/8DAwP+5ubn/srKy/6ur
+ q/+kpKT/nJyc/5WVlv+Ojo7/h4eH/4GBgf9NTU3/IyQk/ygpKP8qKSn/KSkp/xgYGNkODg5cDQ0NKgYG
+ BgQAAAAAAAAAAAAAAACFhYW/YGBf/15eXv9aWln/TU1N/7a2tv/e3t7/1dXV/87Pz//Hx8f/wcHB/7m5
+ uv+ysrP/rKyr/6SkpP+dnZ3/lZWW/46Ojv+Hh4f/gYGB/1BQUP8kJCT/KSkp/ykpKf8oKCj/GhkZ2Q4O
+ DlwNDQ0qBgYGBAAAAAAAAAAAAAAAAIiGhr9gYGD/Xl5e/1paWv9PT0//t7e3/93d3f/U1NT/zs7O/8fH
+ x//AwMD/ubm5/7Kysv+rq6v/o6Ok/5ycnP+VlZX/jo6N/4aGhv+BgYH/U1NT/yYmJv8qKir/Kisq/ygo
+ Kf8bHBzYDg4OXA0NDSoGBgYEAAAAAAAAAAAAAAAAioqKv19fX/9eXl7/Wlta/1FRUf+srKz/4uLi/9LS
+ 0v/Mzcz/xcXG/7+/v/+4ubj/srKx/6urq/+kpKT/nZ2d/5WVlf+Njo7/h4aH/4GBgf9TUlL/KSkp/yws
+ LP8qLzH/Jy4v/x4eHtgNDQ1cDQ0NKgYGBgQAAAAAAAAAAAAAAACMi4y/Xl5e/11dXf9aWlr/VVVV/1xc
+ XP+qqqr/sbGx/66urv+qqqr/pKSj/52dnf+VlZX/jo6O/4eHh/+Af3//d3l3/3BwcP9paWn/XFxc/zMz
+ M/8sLCz/LS0t/yswMf8nLS7/ICAg2A0NDVwNDQ0qBgYGBAAAAAAAAAAAAAAAAI6Ojr9cXFz/XFxc/1pa
+ Wv9WV1f/UFFQ/0xMS/9HR0f/RERE/0BBQP8+Pj7/PDw8/zo7Ov84ODj/ODg4/zU1Nf8zMzP/MTEx/zAw
+ MP8uLi//Li4u/y4tL/8qPUD/KDk+/yU4O/8jIiLYDQ0NXA0NDSoGBgYEAAAAAAAAAAAAAAAAkZGRv1pb
+ W/9bW1r/WFlY/1ZWVv9UVFT/UFBQ/05OTv9MTEz/SklK/0dHR/9FRUX/QkJC/0BAQP8+Pj7/PDw8/zo6
+ Ov83ODf/NTU1/zIyMv8xMTH/Ly4u/yk7P/8oO0D/JTpA/yUkJNgNDQ1bDQ0NKgcHBwQAAAAAAAAAAAAA
+ AACTk5O/WFhY/1lZWf9YV1j/VVVV/1JSUv9QUFD/Tk5O/01MTf9KSkr/SEhI/0ZGRv9DQkP/QEFA/z8/
+ P/89PT3/Ozs6/zg4OP82NTX/MzMz/zExMf8vLi3/IVtn/yovMf8nLi//KCgo0gwMDEcMDAwgBwcHAwAA
+ AAAAAAAAAAAAAJKTkr9VVFX/VFVV/1RUVP9SUVH/T09P/01NTv9MS0z/SkpK/0hJSP9HR0f/REVE/0FB
+ Qf8/Pz//Pj4+/zs7PP85Ojn/Nzc3/zQ0NP8xMTH/LzAw/y4uLv8tLCz/KS8w/yUtLv8tLS3FCgoKFAoK
+ CgkDAwMBAAAAAAAAAAAAAAAAl5aXj5KSkr+QkJC/jYuLv4eHh7+EhIS/gICAv3x8fL93d3e/dHR0v3Bw
+ cL9samy/ZmZmv2NjY79fX1+/W1tbv1VVVb9SUlK/Tk5Ov0pKSr9ERES/QUFBvz09Pb85OTm/MzMzvzEx
+ MY8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////////////////gAAAH4AAAB+AA
+ AAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AA
+ AAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB////////////////ygAAAAwAAAAYAAAAAEA
+ IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAA
+ AAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAA
+ AAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAACCAgIBwkJCQwICAgOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcH
+ Bw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcH
+ Bw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOCAgIDgkJCQwICAgHAAAAAgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAICAgHCwsLGQ0NDSwNDQ0yDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0N
+ DTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0N
+ DTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMg0NDSwLCwsaCAgIBwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJCQkMDQ0NLA0NDUwODg5XDg4OWQ4ODlkODg5ZDg4OWQ4O
+ DlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4O
+ DlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OVw0N
+ DUwNDQ0sCQkJDAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEFBQUOCgoKMgsLC1cLCwtkCwsLZgsL
+ C2YLCwtmCwsLZgwMDGYMDAxmDAwMZgwMDGYMDAxmDAwMZgwMDGYMDAxmDAwMZg0NDWYNDQ1mDQ0NZg0N
+ DWYNDQ1mDQ0NZg0NDWYNDQ1mDg4OZg4ODmYODg5mDg4OZg4ODmYODg5mDg4OZg4ODmYODg5mDg4OZg4O
+ DmYODg5mDg4OZA4ODlcNDQ0yCAgIDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAGJiYv9cXFz/Wlpa/1VV
+ V/9TU1L/UVFR/05OTv9LSkv/R0dH/0NDQ/9BQUH/Pz4//zw8PP86OTn/NTU1/zIyMv8wMDD/LS0u/yoq
+ Kv8mJib/JCMk/yEhIf8eHh7/Gxsc/xkZGf8UFBT/ERER/w8PD/8ODg7/Dg4O/w4ODv8ODg7/Dg4O/w4O
+ Dv8ODg7/Dg4O/w4ODv8PDw//Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAGJi
+ Yf8+PDz/Pzw7/0A7Ov9AOzr/Pzo5/z06Ov89Ojr/Ozs7/zo7Ov87Ojv/Ojo6/zk5Of84ODj/Nzc3/zY2
+ Nf81NTT/MzMz/zIyMv8xMTH/MTIx/zAwMP8wMDD/Ly4u/y4tLf8sKiv/Kigo/yknJ/8oJiX/JiQk/yUj
+ I/8kIiH/IiEg/yAeHv8gHh3/IB0d/x8eHv8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAGNjY/9BPj3/Gpiz/xuWsP8alrD/Gpey/yKClv8+PT3/PT09/zw8PP87Ozv/Ojo6/zk5
+ Of84ODj/Nzc3/zY2Nv80NDT/MzMz/zMyMv8yMTH/MDEw/y8vL/8vLy//Li4t/yJWYf8hVF//IVRf/x9T
+ Xf8gU13/H1Nc/x9RXP8eUFv/HlFb/x1QWv8cT1n/HFBb/x8eHv8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAGRkZP9CPTz/GpWv/xySq/8blK3/JH+S/0A8O/8/Pj7/Pj0+/z08
+ PP87Ozv/Ojo6/zk5Of84ODj/Njc3/zU1Nf80NDT/MzMz/zIyMv8xMTH/MDAv/y8vL/8uLi7/LS0s/ywq
+ Kv8tKSj/KiYm/yklJf8nJCP/KCIi/yYiIf8lICD/JB8e/yMeHP8iHRz/Hx0d/x8eH/8ODg7/Dg4OZg4O
+ DlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAGVlZf9GQUD/Gpaw/xuUrf8kgJP/Qj49/0A/
+ P/8/Pj//Pj4+/zw8PP86Ojr/OTk5/zc3N/82NTb/NDQ0/zMzM/8yMjL/MTEx/zAwMP8vLzD/Ly8v/y4u
+ Lv8tLS3/LCws/ysrKv8gVV//H1Nd/x9UXf8gU13/H1Nc/x9RXP8fUVz/HlFb/x5QW/8dUFv/Hx4f/x8f
+ IP8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAGZmZv9GQkL/GZex/yWB
+ k/9GQUH/QkFB/0FBQP8/Pz//PT09/zo7Ov84ODj/NTY1/zMzM/8yMjL/MTEx/zAwMP8vLy//Ly8v/y4u
+ Lv8uLi7/LS0t/ysrK/8qKiv/KSkp/ygnJ/8nJib/JiQk/yYjJP8lIyP/JSIj/yUjI/8kIiL/JCIi/yMh
+ Iv8iISD/IR8g/x8fH/8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAGho
+ aP9IRUX/JIOY/0dDQv9HRUX/Q0ND/0FBQP8/Pz7/Ozo7/zY2Nv8xMTH/Li4u/ywsLf8tLS3/LCws/ysr
+ K/8pKin/KSkp/ygoKP8oKCj/Jycn/ycmJv8lJSX/JSQl/yQkJP8jJCP/IyIj/yIiIv8iIyL/IyMj/yQj
+ JP8kJCT/IyMk/yMjI/8jIyP/IiIh/yAgIP8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAGlqav9IR0f/SUdH/0lHR/9HR0b/RERF/0FBQf88PDz/Pj8//317ff91dXX/cHBw/2tr
+ a/9lZGX/YF9f/1paWv9VVVb/UVFR/0xMTP9HR0f/QUFB/z48PP83ODf/MzMz/zAwMP8wMDD/Ly8w/zAw
+ MP8xMDH/Jycn/yEhIv8jIyP/JCQk/yQkJP8jIyT/IyIi/yEhIf8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAG1ra/9KSkr/SkpK/0lJSf9ISEj/RkVF/0BAQP9CQkL/ycnJ/6ur
+ q/+fn57/np6e/5ycnP+ampr/l5eX/5SUlP+SkpH/j4+P/4yMjP+Iior/hoeG/4ODg/+AgID/fHx8/3h4
+ eP90dHP/cXFx/3Jycv9lZWX/Tk9O/ycnJ/8iIiL/IyQj/yQkJP8jIyP/IyMj/yMhI/8ODg7/Dg4OZg4O
+ DlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAG5ubf9LS0z/S0xL/0tLS/9JSUn/RkZG/0A/
+ P/+Mi4z/s7Oz/6Ojo/+ioqL/oKCg/56env+cnJz/mZqZ/5eWl/+UlJT/kJGR/46Ojv+Li4v/h4eH/4OD
+ g/+Af4D/fHx8/3h4eP91dHT/cHBw/29vb/9wcHD/ZWVl/zAwMP8iIiL/IyMj/yQkJP8kJCT/JCMk/yMk
+ I/8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAHBwb/9NTU3/TU1N/0xM
+ TP9KSkr/R0dH/z8+P/+Ojo7/q6ur/6mpqf+np6b/paSk/6Kiov+goKD/nZ6e/5ubm/+YmJj/lZSU/5GR
+ kf+Ojo7/ioqL/4eHh/+Dg4P/f39//3x8fP93d3f/c3Nz/29vb/9vb2//cnJy/y8vL/8gISD/IyMj/yUk
+ JP8kJCT/JCQk/yQkJP8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAHFx
+ cf9OTk7/Tk5P/01NTf9MTEz/SEhI/0BAQP+QkJD/sLCv/62trf+srKv/qamp/6enp/+kpKX/oaKh/5+f
+ n/+cnJz/mJiY/5WVlf+RkZL/jo6O/4qKiv+Ghob/goKC/35+fv96env/dnZ2/3Fycf9vb2//cnJy/y8u
+ Lv8hICH/IyMj/yQkJf8lJSX/JCQl/yUlJP8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAHNzc/9PT0//T09P/09PT/9NTUz/SUlJ/0FAQf+SkpL/tbS0/7Gxsf+vr7D/rq6u/6ur
+ q/+pqan/pqWl/6Kiov+fn5//nJyc/5iZmP+UlZX/kZGR/42Njf+JiYn/hYWF/4GBgf99fX3/eXl5/3R0
+ dP9wcHD/cnJy/y4uLv8hISD/JCQk/yUlJf8mJSb/JiUl/yUlJf8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAHR0dP9RUVH/UVBR/09PT/9OTk7/S0pK/0JCQv+VlZX/uLi4/7a1
+ tf+zs7P/sbGx/6+vr/+tra3/qaqq/6ampv+ioqP/n5+f/5ycnP+YmJj/lJSU/5CQj/+MjIz/iIiI/4OD
+ g/9/f3//e3t7/3d3dv9ycnL/cnJy/y4vL/8hISH/JCQk/yYmJf8mJib/JiYl/yYlJf8ODg7/Dg4OZg4O
+ DlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAHV1df9TU1T/U1NT/1BRUf9PTk7/TExM/0JC
+ Qv+Xl5f/vr6+/7q6uv+3uLf/tbW1/7Kysv+wsLD/rq2t/6uqrP+mp6b/oqKi/5+fn/+bm5v/l5aX/5KS
+ kv+Oj47/i4qK/4aGhv+BgoH/fX5+/3l5ef90dHT/c3Nz/y8vL/8jISP/JCQk/yYmJv8nJif/JiYm/yYm
+ Jv8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAHZ3dv9VVVX/VVVV/1NS
+ Uv9QUFD/TU1N/0RERP+ampr/wsLC/76/v/+8vLz/ubm6/7a2t/+zs7P/ra2t/6ampv+io6P/np6f/5ub
+ mv+Wl5f/k5OS/46Ojv+Njo3/jY2N/4mJiP+Eg4P/f39//3t7e/92d3b/dXV0/y8vL/8hISH/JCUl/yYm
+ Jv8nJyf/JyYm/yYnJv8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAHh3
+ eP9WVlb/VlZW/1RUVP9RUVH/Tk5O/0VERP+cnJz/xsbG/8LCw//AwMD/vb69/7q7uv+3t7f/sLCw/6mp
+ qf+mpqb/oqGi/52dnf+ZmZn/lZWV/5SUlP+Tk5P/j4+P/4uLi/+Ghob/gYGB/319ff94eHj/dnd2/y8v
+ L/8hIiP/JSUl/ycnJv8oJyj/KCcn/ycnJ/8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAHl5ef9YWFj/V1dX/1ZWVv9SU1P/T09P/0ZGRv+fn5//ysvK/8bGxv/DxMT/wcHB/729
+ vv+6urr/s7Oz/6ysrP+oqKj/pKWk/6CgoP+bm5v/l5eX/5OTk/+SkpL/kJGQ/42Njf+IiIj/g4OD/35/
+ f/96env/eHh4/zAwL/8iIiL/JiYl/ycnJ/8oKCj/Jycn/ygnJ/8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAHp7e/9ZWVr/WVlZ/1dXV/9UVFX/T1BP/0ZGRv+ioaL/z8/P/8rL
+ yv/HyMf/xMTE/8HBwf++vb7/tra2/6+vr/+qq6v/p6en/6Kiov+enp7/mZmZ/5WVlf+UlJT/k5KS/46O
+ jv+Kior/hYWF/4CAgP98fHz/eHl6/zAwMP8jIiP/JiYm/ygnKP8oKCr/KCgo/ycoKP8PDw//Dg4OZg4O
+ DlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAHx8fP9bW1r/Wlpa/1hYWP9VVlb/UFBQ/0dH
+ R/+kpKT/0tLS/87Ozv/Ly8v/x8fH/8PExP/AwMD/ubm5/7Kysf+tra3/qaio/6Wlpf+goKD/m5ub/5eW
+ l/+ZmZr/lJSU/5CQj/+Li4v/hoaG/4GBgf99fX3/e3t7/zAwMP8jIyP/JiYm/ygoJ/8pKSj/KSgo/ygo
+ KP8QEBD/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAH5+ff9cXFz/XFtc/1pZ
+ Wf9XV1b/UVFR/0hISP+lpaX/1tbW/9HR0f/Ozs7/y8rK/8bGxv/DwsL/uLi3/6ysrP+nqaf/o6Oi/56e
+ nv+ioqL/paWl/5+fn/+bmpv/lZaW/5GRkP+NjYz/iIiH/4KCgv9+fn7/fHx8/zEyMv8jIyP/Jicn/ygo
+ KP8pKSn/KCgp/ygpKP8RERH/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAH9/
+ f/9dXV3/XV1d/1paW/9YWFf/UlJS/0lJSf+kpKT/2tra/9TU1P/Q0ND/zc3N/8jJyf/ExMT/vb29/7W1
+ tv+xsbH/rKys/6ioqP+ioqT/nZ2e/5iYmP+YmJj/l5eX/5KSkv+Ojo3/iImI/4ODg/9/f3//fX19/zQ0
+ NP8jIyP/Jycn/ygoKP8pKSn/KSkp/ygoKP8TExP/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAICAgP9eXl7/Xl5e/1xcXP9ZWVn/U1NT/0lJSf+kpKT/3d3d/9fX1v/S0tL/z8/P/8vL
+ y//Gxsb/wsLC/72+vv+4uLn/tLS0/7CwsP+srKz/p6em/6Ghof+dnZ3/mJiY/5KTk/+Ojo7/iYmJ/4SE
+ hP9/gID/fn5+/zY2Nv8kIyT/Jycn/ygoKP8pKSn/KSkp/ykpKf8WFhb/DQ0NZg4ODlkNDQ0zBwcHDgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAIKCgv9fX17/Xl5e/11cXf9ZWln/VFRU/0pJSv+lpaX/4eHg/9na
+ 2v/V1dT/0NDQ/83Mzf/Hx8f/w8PD/7++vv+6urr/tbW1/7CwsP+sra3/p6en/6Kiov+enZ3/mZmY/5SU
+ k/+Pj4//ioqK/4WFhf+AgID/fX19/zk5Of8jIyT/Jycn/ygoKf8pKSn/KSkp/ykpJ/8YFxj/DQ0NZg4O
+ DlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAIOEhP9gYGD/X19f/15dXf9aWlr/VVVV/0tK
+ S/+lpaX/4eLi/9vb2//W1tX/0dHR/83Nzf/IyMj/w8PE/7+/v/+6u7r/tbW1/7Gxsf+tra3/qKio/6Kj
+ o/+enp7/mZmZ/5SUlP+Pj4//i4qK/4WFhf+AgID/fn59/zw8PP8kJCT/Jycn/ykpKf8qKin/KSkp/ygn
+ KP8ZGRr/DQ0NZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAISEhP9gYGD/X19f/15e
+ Xv9aWlv/VlZW/0tLS/+lpaX/4uLi/9zc3P/W19b/0dLR/83Ozv/JyMn/xMTE/7/AwP+7urv/trW2/7Gx
+ sf+tra3/qKin/6Ojov+enp7/mZmZ/5SUlP+Pj5D/i4qK/4aFhf+AgID/fn5+/z9AQP8lJSX/KCgn/ykp
+ Kf8qKin/KSkp/ygoKP8bGxv/DQ0NZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAIWH
+ h/9gYGD/X19f/15eXv9aWlv/VlZX/0xMTP+mpqb/4eLh/9vb2//W1tb/0dHR/83Nzf/IyMn/xMTE/7+/
+ v/+7u7v/tba1/7Gxsf+tra3/qKio/6Ojo/+enp7/mZmZ/5SUlP+Pj4//ioqK/4WFhf+AgID/fX59/0JC
+ Qv8mJib/KCgo/ykpKf8qKir/KSkp/ygoKP8cHBz/DQ0NZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIiIiP9gYGD/X19f/15eXv9bW1v/WFdX/05OTf+np6f/4eHh/9rZ2v/V1dX/0NDQ/83N
+ zf/IyMf/w8PD/76/v/+6urr/tbW1/7CxsP+sra3/p6in/6Kiov+enp7/mZmZ/5OUlP+Pj4//ioqK/4WE
+ hf+AgID/fn19/0ZGRv8mJyb/Kikq/yorKv8qKyr/KSkp/ygoKP8dHh7/DQ0NZg4ODlkNDQ0zBwcHDgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAImJif9gYGD/X19f/15eXv9bW1v/WFhY/1BQUP+pqan/6Ojo/9bW
+ 1v/S09P/z8/P/8vLy//Gxsb/wsLC/76+vv+5ubn/tLS0/7CwsP+srKv/p6em/6Giov+dnZ3/mJiY/5OT
+ k/+Oj47/iYmJ/4SEhP9/f4D/e3t7/0pKS/8oKCj/Kysr/ywsLP8rKir/Kikq/yknJ/8fHx//DQ0NZg4O
+ DlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAIuLi/9fX17/Xl5f/11dXf9bW1v/WVhY/1RU
+ VP9XV1j//////+Pj4//T09P/z8/P/8rKyv/Fx8f/wcHC/7++v/+5ubn/tbW1/7CwsP+sraz/pqao/6Ki
+ ov+enZ7/mZmZ/5STlP+QkJD/i4uL/4aGhv+BgYH/fHx8/zEwL/8rKiz/LCws/y0sLP8rKir/F4GW/ygm
+ J/8iIiL/DQ0NZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAIyMjP9eXV3/Xl5e/11c
+ XP9bW1v/WFlZ/1ZWVf9OTk7/VldW/6enp/+lpaX/pKSk/6Kiov+goKD/nJyc/5iYmP+Tk5P/jo+P/4mJ
+ if+FhIX/gICA/3t7fP92dnb/cXJx/21tbf9nZmb/YmJi/11dXf9aWlr/MzMz/ywtLP8uLi3/LS0t/y0t
+ Lf8sKin/KScm/ycmJP8kJCT/DQ0NZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAI6O
+ jv9cXlz/Xl5e/1tbXP9aWlr/WFhY/1ZWV/9SU1P/Tk9P/0tLSv9HR0f/RERE/0JCQv9AQED/Pj8//zw8
+ Pf87Ozv/Ozs8/zo6Ov85OTn/ODg4/zY2Nv81NDX/NDM0/zMzM/8xMTH/MDAw/y8vL/8vLy//Li4u/y8v
+ L/8uLy7/Li0t/y0tLP8rKij/F4GW/ygmJ/8mJib/DQ0NZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJCPkP9dW1v/XV1c/1tbW/9ZWVn/WFhY/1ZWVv9TVFP/UlJR/09PT/9OTk3/S0xL/0pK
+ Sv9ISEj/R0ZH/0VERf9CQkP/QUFC/0BAQP8/Pz//Pj4+/z09Pf87Ozv/OTk6/zg4OP82Njf/NTU1/zMz
+ M/8yMjL/MTEx/y8wL/8vLy//Ly0t/xeAlf8sKCf/KScm/ykmJf8nJyf/DQ0NZg4ODlkNDQ0zBwcHDgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAJKSkv9aWlr/W1tb/1paWv9ZWVj/V1dX/1ZVVv9UVFT/UlJR/1BP
+ UP9OTk7/TU1N/0xMTP9KSkr/SElI/0dHR/9GRkb/RERE/0JCQv9AQED/Pz8//z4+Pv89PT3/Ozs7/zk5
+ Of84ODj/Nzc2/zQ0NP8zMzP/MjIy/zAwMP8vLy//Lyws/y4qK/8tKCf/GI6q/ygnJv8pKCn/DQ0NZA4O
+ DlcNDQ0yCAgIDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAJOTk/9ZWFj/Wlpa/1lZWf9YWFj/V1dW/1VV
+ VP9TU1P/UVFR/1BPUP9PT0//TU5O/0xMTP9LSkv/SUlJ/0hISP9GRkb/RERE/0NCQv9BQUH/QD8//z4/
+ Pv89PT7/Ozw8/zo6Ov85OTn/Nzg3/zU1NP8zMzP/MTIy/zAwMP8vLy//Li0t/xeAlf8tJyj/KyYm/ygk
+ Jf8rKyv/DQ0NVw0NDUwNDQ0sCQkJDAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAJOTk/9XV1f/WVhY/1hY
+ V/9XV1f/VlZW/1VVVf9SUlL/UFFR/09PT/9OTk7/TU1N/0xMTP9LSkr/SUlJ/0dHR/9GRkb/REVE/0JC
+ Qv9BQUD/Pz8//z8/Pv89PT3/Ozw8/zo6Ov84ODj/Nzc2/zQ0Nf8zMzP/MTIy/zAwL/8vLy//Li0t/y0s
+ LP8rKSj/GI6q/yclJf8tLS3/DAwMMg0NDSwLCwsaCAgIBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKS
+ kv9UVVX/VVVV/1RVVf9TU1P/UlJS/1FRUf9PT0//Tk5O/01NTf9MTEz/SktL/0tJSf9JSUn/SEhI/0ZG
+ R/9FRUX/Q0ND/0FBQf9APz//Pj4+/z0+Pf88PDz/Ojo6/zk5Of84ODj/NjY2/zM0M/8yMjH/MDAw/y8v
+ L/8uLi7/LS0t/y0tLf8rKSn/KSYm/yclJP8vLy//BwcHDgkJCQwICAgHAAAAAgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJaVlf+TkpL/kpKS/4+Qj/+NjY3/iYmJ/4eHhv+FhYX/goKD/3+Af/99fHz/enl5/3Z2
+ dv90dHT/cnJy/3Bwb/9ra2v/aGho/2VmZf9jZGP/YWFh/15eX/9cXFz/WFhY/1VUVf9TUlL/UFBQ/01N
+ Tf9LS0v/SEhI/0NEQ/9BQUH/Pz8//zw9PP85OTn/NjY2/zIyMv8xMTH/AAAAAQAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD///////8AAP///////wAA////////AAD///////8AAP///////wAA+AAAAAAfAAD4AAAAAB8AAPgA
+ AAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+ AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgA
+ AAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+ AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgA
+ AAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAP///////wAA////////
+ AAD///////8AAP///////wAA////////AAA=
+
+
+
\ No newline at end of file
diff --git a/LibreHardwareMonitor/UI/MainForm.Designer.cs b/LibreHardwareMonitor/UI/MainForm.Designer.cs
index 431e91e..14feea4 100644
--- a/LibreHardwareMonitor/UI/MainForm.Designer.cs
+++ b/LibreHardwareMonitor/UI/MainForm.Designer.cs
@@ -117,6 +117,7 @@ namespace LibreHardwareMonitor.UI
this.webMenuItem = new System.Windows.Forms.MenuItem();
this.runWebServerMenuItem = new System.Windows.Forms.MenuItem();
this.serverPortMenuItem = new System.Windows.Forms.MenuItem();
+ this.authWebServerMenuItem = new System.Windows.Forms.MenuItem();
this.helpMenuItem = new System.Windows.Forms.MenuItem();
this.aboutMenuItem = new System.Windows.Forms.MenuItem();
this.treeContextMenu = new System.Windows.Forms.ContextMenu();
@@ -128,51 +129,51 @@ namespace LibreHardwareMonitor.UI
this.splitContainer.Panel1.SuspendLayout();
this.splitContainer.SuspendLayout();
this.SuspendLayout();
- //
+ //
// sensor
- //
+ //
this.sensor.Header = "Sensor";
this.sensor.SortOrder = System.Windows.Forms.SortOrder.None;
this.sensor.TooltipText = null;
this.sensor.Width = 250;
- //
+ //
// value
- //
+ //
this.value.Header = "Value";
this.value.SortOrder = System.Windows.Forms.SortOrder.None;
this.value.TooltipText = null;
this.value.Width = 100;
- //
+ //
// min
- //
+ //
this.min.Header = "Min";
this.min.SortOrder = System.Windows.Forms.SortOrder.None;
this.min.TooltipText = null;
this.min.Width = 100;
- //
+ //
// max
- //
+ //
this.max.Header = "Max";
this.max.SortOrder = System.Windows.Forms.SortOrder.None;
this.max.TooltipText = null;
this.max.Width = 100;
- //
+ //
// nodeImage
- //
+ //
this.nodeImage.DataPropertyName = "Image";
this.nodeImage.LeftMargin = 1;
this.nodeImage.ParentColumn = this.sensor;
this.nodeImage.ScaleMode = Aga.Controls.Tree.ImageScaleMode.Fit;
- //
+ //
// nodeCheckBox
- //
+ //
this.nodeCheckBox.DataPropertyName = "Plot";
this.nodeCheckBox.EditEnabled = true;
this.nodeCheckBox.LeftMargin = 3;
this.nodeCheckBox.ParentColumn = this.sensor;
- //
+ //
// nodeTextBoxText
- //
+ //
this.nodeTextBoxText.DataPropertyName = "Text";
this.nodeTextBoxText.EditEnabled = true;
this.nodeTextBoxText.IncrementalSearchEnabled = true;
@@ -180,44 +181,44 @@ namespace LibreHardwareMonitor.UI
this.nodeTextBoxText.ParentColumn = this.sensor;
this.nodeTextBoxText.Trimming = System.Drawing.StringTrimming.EllipsisCharacter;
this.nodeTextBoxText.UseCompatibleTextRendering = true;
- //
+ //
// nodeTextBoxValue
- //
+ //
this.nodeTextBoxValue.DataPropertyName = "Value";
this.nodeTextBoxValue.IncrementalSearchEnabled = true;
this.nodeTextBoxValue.LeftMargin = 3;
this.nodeTextBoxValue.ParentColumn = this.value;
this.nodeTextBoxValue.Trimming = System.Drawing.StringTrimming.EllipsisCharacter;
this.nodeTextBoxValue.UseCompatibleTextRendering = true;
- //
+ //
// nodeTextBoxMin
- //
+ //
this.nodeTextBoxMin.DataPropertyName = "Min";
this.nodeTextBoxMin.IncrementalSearchEnabled = true;
this.nodeTextBoxMin.LeftMargin = 3;
this.nodeTextBoxMin.ParentColumn = this.min;
this.nodeTextBoxMin.Trimming = System.Drawing.StringTrimming.EllipsisCharacter;
this.nodeTextBoxMin.UseCompatibleTextRendering = true;
- //
+ //
// nodeTextBoxMax
- //
+ //
this.nodeTextBoxMax.DataPropertyName = "Max";
this.nodeTextBoxMax.IncrementalSearchEnabled = true;
this.nodeTextBoxMax.LeftMargin = 3;
this.nodeTextBoxMax.ParentColumn = this.max;
this.nodeTextBoxMax.Trimming = System.Drawing.StringTrimming.EllipsisCharacter;
this.nodeTextBoxMax.UseCompatibleTextRendering = true;
- //
+ //
// mainMenu
- //
+ //
this.mainMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.fileMenuItem,
this.viewMenuItem,
this.optionsMenuItem,
this.helpMenuItem});
- //
+ //
// fileMenuItem
- //
+ //
this.fileMenuItem.Index = 0;
this.fileMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.saveReportMenuItem,
@@ -227,26 +228,26 @@ namespace LibreHardwareMonitor.UI
this.menuItem6,
this.exitMenuItem});
this.fileMenuItem.Text = "File";
- //
+ //
// saveReportMenuItem
- //
+ //
this.saveReportMenuItem.Index = 0;
this.saveReportMenuItem.Text = "Save Report...";
this.saveReportMenuItem.Click += new System.EventHandler(this.SaveReportMenuItem_Click);
- //
+ //
// MenuItem2
- //
+ //
this.MenuItem2.Index = 1;
this.MenuItem2.Text = "-";
- //
+ //
// resetMenuItem
- //
+ //
this.resetMenuItem.Index = 2;
this.resetMenuItem.Text = "Reset";
this.resetMenuItem.Click += new System.EventHandler(this.ResetClick);
- //
+ //
// menuItem5
- //
+ //
this.menuItem5.Index = 3;
this.menuItem5.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.mainboardMenuItem,
@@ -257,55 +258,55 @@ namespace LibreHardwareMonitor.UI
this.hddMenuItem,
this.nicMenuItem});
this.menuItem5.Text = "Hardware";
- //
+ //
// mainboardMenuItem
- //
+ //
this.mainboardMenuItem.Index = 0;
this.mainboardMenuItem.Text = "Motherboard";
- //
+ //
// cpuMenuItem
- //
+ //
this.cpuMenuItem.Index = 1;
this.cpuMenuItem.Text = "CPU";
- //
+ //
// ramMenuItem
- //
+ //
this.ramMenuItem.Index = 2;
this.ramMenuItem.Text = "RAM";
- //
+ //
// gpuMenuItem
- //
+ //
this.gpuMenuItem.Index = 3;
this.gpuMenuItem.Text = "GPU";
- //
+ //
// fanControllerMenuItem
- //
+ //
this.fanControllerMenuItem.Index = 4;
this.fanControllerMenuItem.Text = "Fan Controllers";
- //
+ //
// hddMenuItem
- //
+ //
this.hddMenuItem.Index = 5;
this.hddMenuItem.Text = "Hard Disk Drives";
- //
+ //
// nicMenuItem
- //
+ //
this.nicMenuItem.Index = 6;
this.nicMenuItem.Text = "Network";
- //
+ //
// menuItem6
- //
+ //
this.menuItem6.Index = 4;
this.menuItem6.Text = "-";
- //
+ //
// exitMenuItem
- //
+ //
this.exitMenuItem.Index = 5;
this.exitMenuItem.Text = "Exit";
this.exitMenuItem.Click += new System.EventHandler(this.ExitClick);
- //
+ //
// viewMenuItem
- //
+ //
this.viewMenuItem.Index = 1;
this.viewMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.resetMinMaxMenuItem,
@@ -316,64 +317,64 @@ namespace LibreHardwareMonitor.UI
this.MenuItem1,
this.columnsMenuItem});
this.viewMenuItem.Text = "View";
- //
+ //
// resetMinMaxMenuItem
- //
+ //
this.resetMinMaxMenuItem.Index = 0;
this.resetMinMaxMenuItem.Text = "Reset Min/Max";
this.resetMinMaxMenuItem.Click += new System.EventHandler(this.ResetMinMaxMenuItem_Click);
- //
+ //
// MenuItem3
- //
+ //
this.MenuItem3.Index = 1;
this.MenuItem3.Text = "-";
- //
+ //
// hiddenMenuItem
- //
+ //
this.hiddenMenuItem.Index = 2;
this.hiddenMenuItem.Text = "Show Hidden Sensors";
- //
+ //
// plotMenuItem
- //
+ //
this.plotMenuItem.Index = 3;
this.plotMenuItem.Text = "Show Plot";
- //
+ //
// gadgetMenuItem
- //
+ //
this.gadgetMenuItem.Index = 4;
this.gadgetMenuItem.Text = "Show Gadget";
- //
+ //
// MenuItem1
- //
+ //
this.MenuItem1.Index = 5;
this.MenuItem1.Text = "-";
- //
+ //
// columnsMenuItem
- //
+ //
this.columnsMenuItem.Index = 6;
this.columnsMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.valueMenuItem,
this.minMenuItem,
this.maxMenuItem});
this.columnsMenuItem.Text = "Columns";
- //
+ //
// valueMenuItem
- //
+ //
this.valueMenuItem.Index = 0;
this.valueMenuItem.Text = "Value";
- //
+ //
// minMenuItem
- //
+ //
this.minMenuItem.Index = 1;
this.minMenuItem.Text = "Min";
- //
+ //
// maxMenuItem
- //
+ //
this.maxMenuItem.Index = 2;
this.maxMenuItem.Text = "Max";
- //
+ //
// optionsMenuItem
- //
+ //
this.optionsMenuItem.Index = 2;
this.optionsMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.startMinMenuItem,
@@ -390,93 +391,93 @@ namespace LibreHardwareMonitor.UI
this.webMenuItemSeparator,
this.webMenuItem});
this.optionsMenuItem.Text = "Options";
- //
+ //
// startMinMenuItem
- //
+ //
this.startMinMenuItem.Index = 0;
this.startMinMenuItem.Text = "Start Minimized";
- //
+ //
// minTrayMenuItem
- //
+ //
this.minTrayMenuItem.Index = 1;
this.minTrayMenuItem.Text = "Minimize To Tray";
- //
+ //
// minCloseMenuItem
- //
+ //
this.minCloseMenuItem.Index = 2;
this.minCloseMenuItem.Text = "Minimize On Close";
- //
+ //
// startupMenuItem
- //
+ //
this.startupMenuItem.Index = 3;
this.startupMenuItem.Text = "Run On Windows Startup";
- //
+ //
// separatorMenuItem
- //
+ //
this.separatorMenuItem.Index = 4;
this.separatorMenuItem.Text = "-";
- //
+ //
// temperatureUnitsMenuItem
- //
+ //
this.temperatureUnitsMenuItem.Index = 5;
this.temperatureUnitsMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.celsiusMenuItem,
this.fahrenheitMenuItem});
this.temperatureUnitsMenuItem.Text = "Temperature Unit";
- //
+ //
// celsiusMenuItem
- //
+ //
this.celsiusMenuItem.Index = 0;
this.celsiusMenuItem.RadioCheck = true;
this.celsiusMenuItem.Text = "Celsius";
this.celsiusMenuItem.Click += new System.EventHandler(this.CelsiusMenuItem_Click);
- //
+ //
// fahrenheitMenuItem
- //
+ //
this.fahrenheitMenuItem.Index = 1;
this.fahrenheitMenuItem.RadioCheck = true;
this.fahrenheitMenuItem.Text = "Fahrenheit";
this.fahrenheitMenuItem.Click += new System.EventHandler(this.FahrenheitMenuItem_Click);
- //
+ //
// plotLocationMenuItem
- //
+ //
this.plotLocationMenuItem.Index = 6;
this.plotLocationMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.plotWindowMenuItem,
this.plotBottomMenuItem,
this.plotRightMenuItem});
this.plotLocationMenuItem.Text = "Plot Location";
- //
+ //
// plotWindowMenuItem
- //
+ //
this.plotWindowMenuItem.Index = 0;
this.plotWindowMenuItem.RadioCheck = true;
this.plotWindowMenuItem.Text = "Window";
- //
+ //
// plotBottomMenuItem
- //
+ //
this.plotBottomMenuItem.Index = 1;
this.plotBottomMenuItem.RadioCheck = true;
this.plotBottomMenuItem.Text = "Bottom";
- //
+ //
// plotRightMenuItem
- //
+ //
this.plotRightMenuItem.Index = 2;
this.plotRightMenuItem.RadioCheck = true;
this.plotRightMenuItem.Text = "Right";
- //
+ //
// logSeparatorMenuItem
- //
+ //
this.logSeparatorMenuItem.Index = 7;
this.logSeparatorMenuItem.Text = "-";
- //
+ //
// logSensorsMenuItem
- //
+ //
this.logSensorsMenuItem.Index = 8;
this.logSensorsMenuItem.Text = "Log Sensors";
- //
+ //
// loggingIntervalMenuItem
- //
+ //
this.loggingIntervalMenuItem.Index = 9;
this.loggingIntervalMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.log1sMenuItem,
@@ -493,87 +494,87 @@ namespace LibreHardwareMonitor.UI
this.log2hMenuItem,
this.log6hMenuItem});
this.loggingIntervalMenuItem.Text = "Logging Interval";
- //
+ //
// log1sMenuItem
- //
+ //
this.log1sMenuItem.Index = 0;
this.log1sMenuItem.RadioCheck = true;
this.log1sMenuItem.Text = "1s";
- //
+ //
// log2sMenuItem
- //
+ //
this.log2sMenuItem.Index = 1;
this.log2sMenuItem.RadioCheck = true;
this.log2sMenuItem.Text = "2s";
- //
+ //
// log5sMenuItem
- //
+ //
this.log5sMenuItem.Index = 2;
this.log5sMenuItem.RadioCheck = true;
this.log5sMenuItem.Text = "5s";
- //
+ //
// log10sMenuItem
- //
+ //
this.log10sMenuItem.Index = 3;
this.log10sMenuItem.RadioCheck = true;
this.log10sMenuItem.Text = "10s";
- //
+ //
// log30sMenuItem
- //
+ //
this.log30sMenuItem.Index = 4;
this.log30sMenuItem.RadioCheck = true;
this.log30sMenuItem.Text = "30s";
- //
+ //
// log1minMenuItem
- //
+ //
this.log1minMenuItem.Index = 5;
this.log1minMenuItem.RadioCheck = true;
this.log1minMenuItem.Text = "1min";
- //
+ //
// log2minMenuItem
- //
+ //
this.log2minMenuItem.Index = 6;
this.log2minMenuItem.RadioCheck = true;
this.log2minMenuItem.Text = "2min";
- //
+ //
// log5minMenuItem
- //
+ //
this.log5minMenuItem.Index = 7;
this.log5minMenuItem.RadioCheck = true;
this.log5minMenuItem.Text = "5min";
- //
+ //
// log10minMenuItem
- //
+ //
this.log10minMenuItem.Index = 8;
this.log10minMenuItem.RadioCheck = true;
this.log10minMenuItem.Text = "10min";
- //
+ //
// log30minMenuItem
- //
+ //
this.log30minMenuItem.Index = 9;
this.log30minMenuItem.RadioCheck = true;
this.log30minMenuItem.Text = "30min";
- //
+ //
// log1hMenuItem
- //
+ //
this.log1hMenuItem.Index = 10;
this.log1hMenuItem.RadioCheck = true;
this.log1hMenuItem.Text = "1h";
- //
+ //
// log2hMenuItem
- //
+ //
this.log2hMenuItem.Index = 11;
this.log2hMenuItem.RadioCheck = true;
this.log2hMenuItem.Text = "2h";
- //
+ //
// log6hMenuItem
- //
+ //
this.log6hMenuItem.Index = 12;
this.log6hMenuItem.RadioCheck = true;
this.log6hMenuItem.Text = "6h";
- //
+ //
// sensorValuesTimeWindowMenuItem
- //
+ //
this.sensorValuesTimeWindowMenuItem.Index = 10;
this.sensorValuesTimeWindowMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.timeWindow30sMenuItem,
@@ -588,146 +589,153 @@ namespace LibreHardwareMonitor.UI
this.timeWindow12hMenuItem,
this.timeWindow24hMenuItem});
this.sensorValuesTimeWindowMenuItem.Text = "Sensor Values Time Window";
- //
+ //
// timeWindow30sMenuItem
- //
+ //
this.timeWindow30sMenuItem.Index = 0;
this.timeWindow30sMenuItem.RadioCheck = true;
this.timeWindow30sMenuItem.Text = "30s";
- //
+ //
// timeWindow1minMenuItem
- //
+ //
this.timeWindow1minMenuItem.Index = 1;
this.timeWindow1minMenuItem.RadioCheck = true;
this.timeWindow1minMenuItem.Text = "1min";
- //
+ //
// timeWindow2minMenuItem
- //
+ //
this.timeWindow2minMenuItem.Index = 2;
this.timeWindow2minMenuItem.RadioCheck = true;
this.timeWindow2minMenuItem.Text = "2min";
- //
+ //
// timeWindow5minMenuItem
- //
+ //
this.timeWindow5minMenuItem.Index = 3;
this.timeWindow5minMenuItem.RadioCheck = true;
this.timeWindow5minMenuItem.Text = "5min";
- //
+ //
// timeWindow10minMenuItem
- //
+ //
this.timeWindow10minMenuItem.Index = 4;
this.timeWindow10minMenuItem.RadioCheck = true;
this.timeWindow10minMenuItem.Text = "10min";
- //
+ //
// timeWindow30minMenuItem
- //
+ //
this.timeWindow30minMenuItem.Index = 5;
this.timeWindow30minMenuItem.RadioCheck = true;
this.timeWindow30minMenuItem.Text = "30min";
- //
+ //
// timeWindow1hMenuItem
- //
+ //
this.timeWindow1hMenuItem.Index = 6;
this.timeWindow1hMenuItem.RadioCheck = true;
this.timeWindow1hMenuItem.Text = "1h";
- //
+ //
// timeWindow2hMenuItem
- //
+ //
this.timeWindow2hMenuItem.Index = 7;
this.timeWindow2hMenuItem.RadioCheck = true;
this.timeWindow2hMenuItem.Text = "2n";
- //
+ //
// timeWindow6hMenuItem
- //
+ //
this.timeWindow6hMenuItem.Index = 8;
this.timeWindow6hMenuItem.RadioCheck = true;
this.timeWindow6hMenuItem.Text = "6h";
- //
+ //
// timeWindow12hMenuItem
- //
+ //
this.timeWindow12hMenuItem.Index = 9;
this.timeWindow12hMenuItem.RadioCheck = true;
this.timeWindow12hMenuItem.Text = "12h";
- //
+ //
// timeWindow24hMenuItem
- //
+ //
this.timeWindow24hMenuItem.Index = 10;
this.timeWindow24hMenuItem.RadioCheck = true;
this.timeWindow24hMenuItem.Text = "24h";
- //
+ //
// webMenuItemSeparator
- //
+ //
this.webMenuItemSeparator.Index = 11;
this.webMenuItemSeparator.Text = "-";
- //
+ //
// webMenuItem
- //
+ //
this.webMenuItem.Index = 12;
this.webMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.runWebServerMenuItem,
- this.serverPortMenuItem});
+ this.serverPortMenuItem,
+ this.authWebServerMenuItem});
this.webMenuItem.Text = "Remote Web Server";
- //
+ //
// runWebServerMenuItem
- //
+ //
this.runWebServerMenuItem.Index = 0;
this.runWebServerMenuItem.Text = "Run";
- //
+ //
// serverPortMenuItem
- //
+ //
this.serverPortMenuItem.Index = 1;
this.serverPortMenuItem.Text = "Port";
this.serverPortMenuItem.Click += new System.EventHandler(this.ServerPortMenuItem_Click);
- //
+ //
+ // authWebServerMenuItem
+ //
+ this.authWebServerMenuItem.Index = 2;
+ this.authWebServerMenuItem.Text = "Authentication";
+ this.authWebServerMenuItem.Click += new System.EventHandler(this.AuthWebServerMenuItem_Click);
+ //
// helpMenuItem
- //
+ //
this.helpMenuItem.Index = 3;
this.helpMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.aboutMenuItem});
this.helpMenuItem.Text = "Help";
- //
+ //
// aboutMenuItem
- //
+ //
this.aboutMenuItem.Index = 0;
this.aboutMenuItem.Text = "About";
this.aboutMenuItem.Click += new System.EventHandler(this.AboutMenuItem_Click);
- //
+ //
// saveFileDialog
- //
+ //
this.saveFileDialog.DefaultExt = "txt";
this.saveFileDialog.FileName = "LibreHardwareMonitor.Report.txt";
this.saveFileDialog.Filter = "Text Documents|*.txt|All Files|*.*";
this.saveFileDialog.RestoreDirectory = true;
this.saveFileDialog.Title = "Save Report As";
- //
+ //
// timer
- //
+ //
this.timer.Interval = 1000;
this.timer.Tick += new System.EventHandler(this.Timer_Tick);
- //
+ //
// splitContainer
- //
+ //
this.splitContainer.Border3DStyle = System.Windows.Forms.Border3DStyle.Raised;
this.splitContainer.Color = System.Drawing.SystemColors.Control;
this.splitContainer.Cursor = System.Windows.Forms.Cursors.Default;
this.splitContainer.Location = new System.Drawing.Point(12, 12);
this.splitContainer.Name = "splitContainer";
this.splitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal;
- //
+ //
// splitContainer.Panel1
- //
+ //
this.splitContainer.Panel1.Controls.Add(this.treeView);
- //
+ //
// splitContainer.Panel2
- //
+ //
this.splitContainer.Panel2.Cursor = System.Windows.Forms.Cursors.Default;
this.splitContainer.Size = new System.Drawing.Size(386, 483);
this.splitContainer.SplitterDistance = 354;
this.splitContainer.SplitterWidth = 5;
this.splitContainer.TabIndex = 3;
- //
+ //
// treeView
- //
+ //
this.treeView.BackColor = System.Drawing.SystemColors.Window;
this.treeView.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.treeView.Columns.Add(this.sensor);
@@ -759,9 +767,9 @@ namespace LibreHardwareMonitor.UI
this.treeView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.TreeView_MouseDown);
this.treeView.MouseMove += new System.Windows.Forms.MouseEventHandler(this.TreeView_MouseMove);
this.treeView.MouseUp += new System.Windows.Forms.MouseEventHandler(this.TreeView_MouseUp);
- //
+ //
// MainForm
- //
+ //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(418, 533);
@@ -871,6 +879,7 @@ namespace LibreHardwareMonitor.UI
private System.Windows.Forms.MenuItem timeWindow6hMenuItem;
private System.Windows.Forms.MenuItem timeWindow12hMenuItem;
private System.Windows.Forms.MenuItem timeWindow24hMenuItem;
+ private System.Windows.Forms.MenuItem authWebServerMenuItem;
}
}
diff --git a/LibreHardwareMonitor/UI/MainForm.cs b/LibreHardwareMonitor/UI/MainForm.cs
index a252246..b6eb0a4 100644
--- a/LibreHardwareMonitor/UI/MainForm.cs
+++ b/LibreHardwareMonitor/UI/MainForm.cs
@@ -267,7 +267,7 @@ namespace LibreHardwareMonitor.UI
celsiusMenuItem.Checked = _unitManager.TemperatureUnit == TemperatureUnit.Celsius;
fahrenheitMenuItem.Checked = !celsiusMenuItem.Checked;
- Server = new HttpServer(_root, _settings.GetValue("listenerPort", 8085));
+ Server = new HttpServer(_root, _settings.GetValue("listenerPort", 8085), _settings.GetValue("authenticationEnabled", false), _settings.GetValue("authenticationUserName", ""), _settings.GetValue("authenticationPassword", ""));
if (Server.PlatformNotSupported)
{
webMenuItemSeparator.Visible = false;
@@ -283,6 +283,8 @@ namespace LibreHardwareMonitor.UI
Server.StopHttpListener();
};
+ authWebServerMenuItem.Checked = _settings.GetValue("authenticationEnabled", false);
+
_logSensors = new UserOption("logSensorsMenuItem", false, logSensorsMenuItem, _settings);
_loggingInterval = new UserRadioGroup("loggingInterval", 0,
@@ -648,6 +650,9 @@ namespace LibreHardwareMonitor.UI
_settings.SetValue("treeView.Columns." + column.Header + ".Width", column.Width);
_settings.SetValue("listenerPort", Server.ListenerPort);
+ _settings.SetValue("authenticationEnabled", Server.AuthEnabled);
+ _settings.SetValue("authenticationUserName", Server.UserName);
+ _settings.SetValue("authenticationPassword", Server.Password);
string fileName = Path.ChangeExtension(Application.ExecutablePath, ".config");
@@ -1028,5 +1033,12 @@ namespace LibreHardwareMonitor.UI
}
public HttpServer Server { get; }
+
+ private void AuthWebServerMenuItem_Click(object sender, EventArgs e)
+ {
+ new AuthForm(this).ShowDialog();
+ }
+
+ public bool AuthWebServerMenuItemChecked { get { return authWebServerMenuItem.Checked; } set { authWebServerMenuItem.Checked = value; } }
}
}
diff --git a/LibreHardwareMonitor/UI/PortForm.Designer.cs b/LibreHardwareMonitor/UI/PortForm.Designer.cs
index d326dd8..5672d54 100644
--- a/LibreHardwareMonitor/UI/PortForm.Designer.cs
+++ b/LibreHardwareMonitor/UI/PortForm.Designer.cs
@@ -34,6 +34,7 @@ namespace LibreHardwareMonitor.UI
///
private void InitializeComponent()
{
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PortForm));
this.portOKButton = new System.Windows.Forms.Button();
this.portCancelButton = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
@@ -45,9 +46,9 @@ namespace LibreHardwareMonitor.UI
this.label5 = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.portNumericUpDn)).BeginInit();
this.SuspendLayout();
- //
+ //
// portOKButton
- //
+ //
this.portOKButton.Location = new System.Drawing.Point(244, 137);
this.portOKButton.Name = "portOKButton";
this.portOKButton.Size = new System.Drawing.Size(75, 23);
@@ -55,9 +56,9 @@ namespace LibreHardwareMonitor.UI
this.portOKButton.Text = "OK";
this.portOKButton.UseVisualStyleBackColor = true;
this.portOKButton.Click += new System.EventHandler(this.PortOKButton_Click);
- //
+ //
// portCancelButton
- //
+ //
this.portCancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.portCancelButton.Location = new System.Drawing.Point(162, 137);
this.portCancelButton.Name = "portCancelButton";
@@ -66,47 +67,47 @@ namespace LibreHardwareMonitor.UI
this.portCancelButton.Text = "Cancel";
this.portCancelButton.UseVisualStyleBackColor = true;
this.portCancelButton.Click += new System.EventHandler(this.PortCancelButton_Click);
- //
+ //
// label1
- //
+ //
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(13, 106);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(377, 13);
this.label1.TabIndex = 3;
this.label1.Text = "Note: You will need to open the port in firewall settings of the operating system" +
- ".";
- //
+ ".";
+ //
// label2
- //
+ //
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(13, 9);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(193, 13);
this.label2.TabIndex = 4;
this.label2.Text = "Port number for the remote web server:";
- //
+ //
// label3
- //
+ //
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(13, 39);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(443, 13);
this.label3.TabIndex = 5;
this.label3.Text = "If the web server is running then it will need to be restarted for the port chang" +
- "e to take effect.";
- //
+ "e to take effect.";
+ //
// label4
- //
+ //
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(13, 62);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(262, 13);
this.label4.TabIndex = 6;
this.label4.Text = "The web server will be accessible from the browser at ";
- //
+ //
// webServerLinkLabel
- //
+ //
this.webServerLinkLabel.AutoSize = true;
this.webServerLinkLabel.Location = new System.Drawing.Point(269, 62);
this.webServerLinkLabel.Name = "webServerLinkLabel";
@@ -115,9 +116,9 @@ namespace LibreHardwareMonitor.UI
this.webServerLinkLabel.TabStop = true;
this.webServerLinkLabel.Text = "linkLabel1";
this.webServerLinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.WebServerLinkLabel_LinkClicked);
- //
+ //
// portNumericUpDn
- //
+ //
this.portNumericUpDn.Location = new System.Drawing.Point(208, 7);
this.portNumericUpDn.Maximum = new decimal(new int[] {
20000,
@@ -138,18 +139,19 @@ namespace LibreHardwareMonitor.UI
0,
0});
this.portNumericUpDn.ValueChanged += new System.EventHandler(this.PortNumericUpDn_ValueChanged);
- //
+ this.portNumericUpDn.KeyUp += new System.Windows.Forms.KeyEventHandler(this.PortNumericUpDn_KeyUp);
+ //
// label5
- //
+ //
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(13, 84);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(304, 13);
this.label5.TabIndex = 9;
this.label5.Text = "You will have to start the server by clicking Run from the menu.";
- //
+ //
// PortForm
- //
+ //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.portCancelButton;
@@ -163,6 +165,8 @@ namespace LibreHardwareMonitor.UI
this.Controls.Add(this.label1);
this.Controls.Add(this.portCancelButton);
this.Controls.Add(this.portOKButton);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "PortForm";
diff --git a/LibreHardwareMonitor/UI/PortForm.cs b/LibreHardwareMonitor/UI/PortForm.cs
index dd569e5..22d9c4e 100644
--- a/LibreHardwareMonitor/UI/PortForm.cs
+++ b/LibreHardwareMonitor/UI/PortForm.cs
@@ -75,5 +75,9 @@ namespace LibreHardwareMonitor.UI
catch { }
}
+ private void PortNumericUpDn_KeyUp(object sender, KeyEventArgs e)
+ {
+ PortNumericUpDn_ValueChanged(null, null);
+ }
}
}
diff --git a/LibreHardwareMonitor/UI/PortForm.resx b/LibreHardwareMonitor/UI/PortForm.resx
index 7080a7d..b7102bd 100644
--- a/LibreHardwareMonitor/UI/PortForm.resx
+++ b/LibreHardwareMonitor/UI/PortForm.resx
@@ -112,9 +112,266 @@
2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ AAABAAMAEBAAAAEAIABoBAAANgAAACAgAAABACAAqBAAAJ4EAAAwMAAAAQAgAKglAABGFQAAKAAAABAA
+ AAAgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEU8OykuDgdIIxQSURwdHU8ZGhpPFhYWTxQU
+ FE8SEhJPDxAPTw0KCk8KBQRPCAQDTwcDAU8HAQBPBgQEUQUFBTxLVVb/L215/zdXXP89Ozv/ODc3/zM0
+ M/8vLy//Kioq/yYlJf8iJif/Gycp/xggI/8UHiD/Eh4g/w4SE/8GBARRQWRr/xGXtP8yUln/NDIx/y4u
+ Lf8qKir/KSgo/ycnJ/8lJCP/Iikq/xs4Pf8aOD7/GzpB/xo4Pf8SGhv/BwMDT01aXP46Ulj+Pzc0/kdH
+ R/5MTU3+Q0ND/jw8PP43Nzf+Ly8v/igoKP4lKCn+Iico/hwiI/4cHyD/FBMU/wYHBk9XVVX+Rj8+/klJ
+ Sf6ioqL+rq+u/p+fn/6YmJj+j4+P/oSEhP56enr+dXJy/mNgYP4iHx7+Gxka/xUVFf8HBwdPW1pa/kVF
+ RP5YWFj+rq6u/r6+vv6wsK/+qamp/qCgoP6UlJT+iYmJ/oGBgf5xcXH+JCQk/hsbG/8WFhb/BwcHT15e
+ Xv5ISEj+Wlpa/rW1tf7Gxsb+tra2/qysq/6hoaL+lpaW/oyMjP6EhIT+cnJy/iQkJP4cHBz/GBgY/wcH
+ B09jY2P+TUxM/l5eXv7AwMD+0dHR/r6+vv6vr6/+o6Ok/pmYmf6Rk5P+iouK/nd4d/4lJSX+HR0d/xkZ
+ Gf8HBwdPZ2dn/lBQUP5iYmL+ysrK/tzc3P7Hxsf+tbS1/qmpqf6fn5/+mJiY/o6Pj/57e3z+JSUm/h4e
+ Hv8aGhr/CAgIT2tra/5TU1P+ZGRk/tLS0v7j5eP+zMzM/ry8vP6wsLD+pqam/pubm/6TkZH+f39//igo
+ KP4fHx7/HBwc/wkJCk9ubm7+VlVW/mZlZv7X1tf+6Ojo/tPS0/7Hx8f+urq6/qurq/6dnp7+lJSU/oGB
+ gP4sLCz+Hx4e/x4dHP8LCwtPb29v/lZWVv5nZ2j+4eHh/vLx8v7Z2dn+zc3N/sDAwP6wsrL+pKOk/pmZ
+ mf6Ghob+MDAw/h8gH/8eHx//DQsNT29vb/5YWFj+WVpa/sHBwf7V1dX+wMC//rW1tP6pqan+m5ub/o6P
+ jv6FhYX+cXFx/i4qKv4gLC7/Hiot/w4JB09vb3D+Wlla/lJSUf5VVVX+YGBg/ltbWv5VVVP+Tk5O/kdH
+ R/5BQUH+Ozs6/jAvL/4oKCj+Izk9/x8tL/8QCQhRbm5u/lVVVf5SUlL+S0tL/kRERP5BQUH+PT09/jk5
+ Of41NTX+MzIy/i8vLv4sKSj+Jy4v/h9DTP8iLjH/Ew0KSHp7ev5qamr+ZWVl/mFhYv5cXFz+WFhY/lNS
+ U/5NTU3+R0ZH/kJCQv49PDz+NzU1/jAxMf4qMTL/Jigp/x4cHCn//wAAAAEAAAABAAAAAQAAAAEAAAAB
+ AAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAKAAAACAAAABAAAAAAQAgAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMBBwcHAwYGBgQGBgYEBgYGBAYG
+ BgQGBgYEBgYGBAYGBgQGBgYEBgYGBAYGBgQGBgYEBgYGBAYGBgQGBgYEBgYGBAYGBgQGBgYEBgYGBAYG
+ BgQGBgYEBgYGBAYGBgQGBgYEBwcHAwUFBQIAAAAAAAAAAAAAAAAAAAAAAAAAAAoKCgkMDAwgDQ0NKg0N
+ DSoNDQ0qDQ0NKg0NDSoNDQ0qDQ0NKg0NDSoNDQ0qDQ0NKg0NDSoNDQ0qDQ0NKg0NDSoNDQ0qDQ0NKg0N
+ DSoNDQ0qDQ0NKg0NDSoNDQ0qDQ0NKg0NDSoMDAwlCgoKEQUFBQIAAAAAAAAAAAAAAAAAAAAACAgIFAoK
+ CkcMDAxbDAwMXAwMDFwMDAxcDAwMXAwNDFwNDQ1cDQ0NXA0NDVwNDQ1cDQ0NXA0NDVwNDQ5cDg4OXA4O
+ DlwODg5cDg4OXA4ODlwODg5cDg4OXA4ODlwODg5cDg4OWw0NDVIMDAwlBwcHAwAAAAAAAAAAAAAAAGFh
+ YY9ZWFjFUVBP0kpJSdhIR0fYQkJC2D0+Ptg5OTnZODc22TMyM9kuLi/ZKysr2SYmJtkjIyPZICAf2Rsb
+ G9kXFxjZExMT2Q8ODtkNDAzZDQwM2A0MDNgNDAzYDQ0N2A0NDdgODQ27Dg4OWw0NDSoGBgYEAAAAAAAA
+ AAAAAAAAYmFhvzxCQ/82Uln/NlJZ/zdPVP89PDz/PDw8/zo6Ov85OTn/ODg4/zY2Nv80NDT/NDQ0/zIy
+ Mv8xMTD/Ly4w/yw1OP8qNjj/JzQ1/yYyNP8kMDL/Ii4w/x8sLv8fKy3/HyIi/w0NDdgODg5cDQ0NKgYG
+ BgQAAAAAAAAAAAAAAABjY2K/OFRa/xqXsv8bk6v/M11l/z49Pf89PT3/Ozs7/zo6Of83Nzj/NTY1/zQ0
+ NP8zMzP/MTEw/y8vL/8uLi7/KzQ2/yk1Nv8nMjT/JjAz/yQvMf8jLjD/ISwu/x8rLf8fISL/DQ0N2A4O
+ DlwNDQ0qBgYGBAAAAAAAAAAAAAAAAGZkZL86V13/GpKs/zJkbv9BPz//Pj8+/zw8PP85OTn/Njc2/zQ0
+ Nf8zMjP/MjIy/zAwMP8vLy//Li4u/y0sLP8qKSn/I0hQ/yJHUP8hRk//IEZO/yBGTv8fRU3/HztB/yAf
+ H/8NDQ3YDg4OXA0NDSoGBgYEAAAAAAAAAAAAAAAAaWdovz5WW/83YWr/RkND/0FAQP89PT3/ODc3/zIy
+ Mf8uLi7/LCws/ysrK/8pKSn/Kioq/ygoKP8nJyf/JSUl/yUkJP8kIyP/IyEh/yMiIv8kIiL/JCMj/yQj
+ I/8iISH/ISAg/w0NDdgODg5cDQ0NKgYGBgQAAAAAAAAAAAAAAABqamq/SUhI/0hHR/9GRkb/QUFB/0ZH
+ Rv9/f4D/gICA/3h4eP9xcXH/a2tr/2RkZP9dXV7/V1dX/09PT/9ISEj/Q0NC/0BAQP9AQED/Ozs7/yYm
+ Jv8jIyP/JCQk/yMjI/8jIyH/DQ0N2A4ODlwNDQ0qBgYGBAAAAAAAAAAAAAAAAG5ubr9LS0v/SkpL/0hI
+ SP9BQUH/i4uL/6ysrP+hoqH/n5+e/52bnf+YmJj/lJSU/5CQj/+Li4v/hYaF/4CAgP97e3r/dXR1/3Fx
+ cf9ra2v/Ozs7/yEhIv8kJCT/JCQk/yQkI/8NDQ3YDg4OXA0NDSoGBgYEAAAAAAAAAAAAAAAAcHBwv01N
+ Tf9MTU3/SUpK/0BAP/+Wlpj/q6ur/6inp/+kpKT/oKGg/52cnP+YmJj/k5OT/46Ojv+IiYj/g4OC/319
+ ff93d3f/cXFx/3Fxcf8/Pz//ISEh/yQkJP8lJSX/JSQk/w0NDdkODg5cDQ0NKgYGBgQAAAAAAAAAAAAA
+ AABycnO/T05P/05PT/9MTEz/QUFB/5ubmv+ysrL/rq6u/6urq/+np6f/oqKi/52dnf+ZmZn/k5OT/42O
+ jv+IiIf/gYGB/3x7fP90dXT/cXFx/z8/P/8hISH/JCQl/yUlJf8lJib/DQ0N2Q4ODlwNDQ0qBgYGBAAA
+ AAAAAAAAAAAAAHR1db9RUVH/UFBQ/01NTf9CQkL/np6e/7i4uP+0s7T/sbGx/62trf+oqKj/o6Oj/52d
+ nf+Yl5f/kZKR/4yMi/+FhYX/fn9//3h4eP9zc3P/Pz8//yIiIv8lJSX/JiYm/yYmJv8NDQ3ZDg4OXA0N
+ DSoGBgYEAAAAAAAAAAAAAAAAdnZ2v1RUVP9TU1P/T09P/0VFRf+kpKT/v7+//7u7u/+2trb/sbGx/6mp
+ qf+jo6P/nZ2d/5eXl/+QkZH/jo2N/4mJif+CgoL/fHx8/3d3d/9AQED/IiIi/yYmJv8nJyf/Jycn/w0N
+ DdkODg5cDQ0NKgYGBgQAAAAAAAAAAAAAAAB4eHi/V1dW/1VVVf9QUFD/RkZG/6moqf/Gxsb/wcHB/7y8
+ vP+2trb/q6ys/6Wlpf+fn5//mZiY/5WUlf+RkpL/jI2M/4WFhf9/fn//enp6/0FBQf8iIiP/JiYm/ygn
+ KP8oJyf/DQ0N2Q4ODlwNDQ0qBgYGBAAAAAAAAAAAAAAAAHp6er9YWVn/V1dX/1JSU/9ISEj/ra2t/8zM
+ zP/Gxsb/wcHB/7u7u/+wsLD/qamp/6Ojo/+cnZ3/lpaW/5OTk/+Pj47/iIiI/4CBgP98fH3/QkJC/yMj
+ I/8nJyf/KCgo/ygoKP8ODg7ZDg4OXA0NDSoGBgYEAAAAAAAAAAAAAAAAfXx9v1tbW/9ZWVn/VFVV/0hJ
+ Sf+xsbH/0tLS/8vLy//FxcX/v7++/7Ozs/+qqqr/pKWk/6Cfn/+ampr/mpia/5GRkf+Li4r/goOD/35+
+ fv9CQ0P/IyQk/ycnJ/8pKSn/KSkp/xAQENkODg5cDQ0NKgYGBgQAAAAAAAAAAAAAAAB+fn6/XV1d/1tb
+ W/9WVlb/S0lJ/7Oysv/W1tb/z8/P/8nJyf/CwsL/tbW1/66trf+np6f/oqKi/5ycnP+ZmJn/k5OT/4yM
+ jP+FhYX/f39//0ZFRv8kJCT/KCgo/ykpKf8pKSn/EhIS2Q4ODlwNDQ0qBgYGBAAAAAAAAAAAAAAAAIGB
+ gb9eXl7/XFxc/1dYV/9KSkr/tLS0/9rb2v/S0tL/zczM/8XFxf+/v7//uLi4/7Gxsf+rq6r/o6Oj/5yc
+ nP+UlZT/jY2N/4aFhv+AgID/SUlI/yMjI/8oKCj/KSkp/ykpKf8UFBTZDg4OXA0NDSoGBgYEAAAAAAAA
+ AAAAAAAAg4ODv19fX/9eXl7/WVhZ/0tLS/+0tLT/3d3d/9TU1P/Ozs7/x8bH/8DAwP+5ubn/srKy/6ur
+ q/+kpKT/nJyc/5WVlv+Ojo7/h4eH/4GBgf9NTU3/IyQk/ygpKP8qKSn/KSkp/xgYGNkODg5cDQ0NKgYG
+ BgQAAAAAAAAAAAAAAACFhYW/YGBf/15eXv9aWln/TU1N/7a2tv/e3t7/1dXV/87Pz//Hx8f/wcHB/7m5
+ uv+ysrP/rKyr/6SkpP+dnZ3/lZWW/46Ojv+Hh4f/gYGB/1BQUP8kJCT/KSkp/ykpKf8oKCj/GhkZ2Q4O
+ DlwNDQ0qBgYGBAAAAAAAAAAAAAAAAIiGhr9gYGD/Xl5e/1paWv9PT0//t7e3/93d3f/U1NT/zs7O/8fH
+ x//AwMD/ubm5/7Kysv+rq6v/o6Ok/5ycnP+VlZX/jo6N/4aGhv+BgYH/U1NT/yYmJv8qKir/Kisq/ygo
+ Kf8bHBzYDg4OXA0NDSoGBgYEAAAAAAAAAAAAAAAAioqKv19fX/9eXl7/Wlta/1FRUf+srKz/4uLi/9LS
+ 0v/Mzcz/xcXG/7+/v/+4ubj/srKx/6urq/+kpKT/nZ2d/5WVlf+Njo7/h4aH/4GBgf9TUlL/KSkp/yws
+ LP8qLzH/Jy4v/x4eHtgNDQ1cDQ0NKgYGBgQAAAAAAAAAAAAAAACMi4y/Xl5e/11dXf9aWlr/VVVV/1xc
+ XP+qqqr/sbGx/66urv+qqqr/pKSj/52dnf+VlZX/jo6O/4eHh/+Af3//d3l3/3BwcP9paWn/XFxc/zMz
+ M/8sLCz/LS0t/yswMf8nLS7/ICAg2A0NDVwNDQ0qBgYGBAAAAAAAAAAAAAAAAI6Ojr9cXFz/XFxc/1pa
+ Wv9WV1f/UFFQ/0xMS/9HR0f/RERE/0BBQP8+Pj7/PDw8/zo7Ov84ODj/ODg4/zU1Nf8zMzP/MTEx/zAw
+ MP8uLi//Li4u/y4tL/8qPUD/KDk+/yU4O/8jIiLYDQ0NXA0NDSoGBgYEAAAAAAAAAAAAAAAAkZGRv1pb
+ W/9bW1r/WFlY/1ZWVv9UVFT/UFBQ/05OTv9MTEz/SklK/0dHR/9FRUX/QkJC/0BAQP8+Pj7/PDw8/zo6
+ Ov83ODf/NTU1/zIyMv8xMTH/Ly4u/yk7P/8oO0D/JTpA/yUkJNgNDQ1bDQ0NKgcHBwQAAAAAAAAAAAAA
+ AACTk5O/WFhY/1lZWf9YV1j/VVVV/1JSUv9QUFD/Tk5O/01MTf9KSkr/SEhI/0ZGRv9DQkP/QEFA/z8/
+ P/89PT3/Ozs6/zg4OP82NTX/MzMz/zExMf8vLi3/IVtn/yovMf8nLi//KCgo0gwMDEcMDAwgBwcHAwAA
+ AAAAAAAAAAAAAJKTkr9VVFX/VFVV/1RUVP9SUVH/T09P/01NTv9MS0z/SkpK/0hJSP9HR0f/REVE/0FB
+ Qf8/Pz//Pj4+/zs7PP85Ojn/Nzc3/zQ0NP8xMTH/LzAw/y4uLv8tLCz/KS8w/yUtLv8tLS3FCgoKFAoK
+ CgkDAwMBAAAAAAAAAAAAAAAAl5aXj5KSkr+QkJC/jYuLv4eHh7+EhIS/gICAv3x8fL93d3e/dHR0v3Bw
+ cL9samy/ZmZmv2NjY79fX1+/W1tbv1VVVb9SUlK/Tk5Ov0pKSr9ERES/QUFBvz09Pb85OTm/MzMzvzEx
+ MY8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////////////////gAAAH4AAAB+AA
+ AAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AA
+ AAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB////////////////ygAAAAwAAAAYAAAAAEA
+ IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAA
+ AAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAA
+ AAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAACCAgIBwkJCQwICAgOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcH
+ Bw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcH
+ Bw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOCAgIDgkJCQwICAgHAAAAAgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAICAgHCwsLGQ0NDSwNDQ0yDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0N
+ DTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0N
+ DTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMg0NDSwLCwsaCAgIBwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJCQkMDQ0NLA0NDUwODg5XDg4OWQ4ODlkODg5ZDg4OWQ4O
+ DlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4O
+ DlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OVw0N
+ DUwNDQ0sCQkJDAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEFBQUOCgoKMgsLC1cLCwtkCwsLZgsL
+ C2YLCwtmCwsLZgwMDGYMDAxmDAwMZgwMDGYMDAxmDAwMZgwMDGYMDAxmDAwMZg0NDWYNDQ1mDQ0NZg0N
+ DWYNDQ1mDQ0NZg0NDWYNDQ1mDg4OZg4ODmYODg5mDg4OZg4ODmYODg5mDg4OZg4ODmYODg5mDg4OZg4O
+ DmYODg5mDg4OZA4ODlcNDQ0yCAgIDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAGJiYv9cXFz/Wlpa/1VV
+ V/9TU1L/UVFR/05OTv9LSkv/R0dH/0NDQ/9BQUH/Pz4//zw8PP86OTn/NTU1/zIyMv8wMDD/LS0u/yoq
+ Kv8mJib/JCMk/yEhIf8eHh7/Gxsc/xkZGf8UFBT/ERER/w8PD/8ODg7/Dg4O/w4ODv8ODg7/Dg4O/w4O
+ Dv8ODg7/Dg4O/w4ODv8PDw//Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAGJi
+ Yf8+PDz/Pzw7/0A7Ov9AOzr/Pzo5/z06Ov89Ojr/Ozs7/zo7Ov87Ojv/Ojo6/zk5Of84ODj/Nzc3/zY2
+ Nf81NTT/MzMz/zIyMv8xMTH/MTIx/zAwMP8wMDD/Ly4u/y4tLf8sKiv/Kigo/yknJ/8oJiX/JiQk/yUj
+ I/8kIiH/IiEg/yAeHv8gHh3/IB0d/x8eHv8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAGNjY/9BPj3/Gpiz/xuWsP8alrD/Gpey/yKClv8+PT3/PT09/zw8PP87Ozv/Ojo6/zk5
+ Of84ODj/Nzc3/zY2Nv80NDT/MzMz/zMyMv8yMTH/MDEw/y8vL/8vLy//Li4t/yJWYf8hVF//IVRf/x9T
+ Xf8gU13/H1Nc/x9RXP8eUFv/HlFb/x1QWv8cT1n/HFBb/x8eHv8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAGRkZP9CPTz/GpWv/xySq/8blK3/JH+S/0A8O/8/Pj7/Pj0+/z08
+ PP87Ozv/Ojo6/zk5Of84ODj/Njc3/zU1Nf80NDT/MzMz/zIyMv8xMTH/MDAv/y8vL/8uLi7/LS0s/ywq
+ Kv8tKSj/KiYm/yklJf8nJCP/KCIi/yYiIf8lICD/JB8e/yMeHP8iHRz/Hx0d/x8eH/8ODg7/Dg4OZg4O
+ DlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAGVlZf9GQUD/Gpaw/xuUrf8kgJP/Qj49/0A/
+ P/8/Pj//Pj4+/zw8PP86Ojr/OTk5/zc3N/82NTb/NDQ0/zMzM/8yMjL/MTEx/zAwMP8vLzD/Ly8v/y4u
+ Lv8tLS3/LCws/ysrKv8gVV//H1Nd/x9UXf8gU13/H1Nc/x9RXP8fUVz/HlFb/x5QW/8dUFv/Hx4f/x8f
+ IP8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAGZmZv9GQkL/GZex/yWB
+ k/9GQUH/QkFB/0FBQP8/Pz//PT09/zo7Ov84ODj/NTY1/zMzM/8yMjL/MTEx/zAwMP8vLy//Ly8v/y4u
+ Lv8uLi7/LS0t/ysrK/8qKiv/KSkp/ygnJ/8nJib/JiQk/yYjJP8lIyP/JSIj/yUjI/8kIiL/JCIi/yMh
+ Iv8iISD/IR8g/x8fH/8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAGho
+ aP9IRUX/JIOY/0dDQv9HRUX/Q0ND/0FBQP8/Pz7/Ozo7/zY2Nv8xMTH/Li4u/ywsLf8tLS3/LCws/ysr
+ K/8pKin/KSkp/ygoKP8oKCj/Jycn/ycmJv8lJSX/JSQl/yQkJP8jJCP/IyIj/yIiIv8iIyL/IyMj/yQj
+ JP8kJCT/IyMk/yMjI/8jIyP/IiIh/yAgIP8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAGlqav9IR0f/SUdH/0lHR/9HR0b/RERF/0FBQf88PDz/Pj8//317ff91dXX/cHBw/2tr
+ a/9lZGX/YF9f/1paWv9VVVb/UVFR/0xMTP9HR0f/QUFB/z48PP83ODf/MzMz/zAwMP8wMDD/Ly8w/zAw
+ MP8xMDH/Jycn/yEhIv8jIyP/JCQk/yQkJP8jIyT/IyIi/yEhIf8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAG1ra/9KSkr/SkpK/0lJSf9ISEj/RkVF/0BAQP9CQkL/ycnJ/6ur
+ q/+fn57/np6e/5ycnP+ampr/l5eX/5SUlP+SkpH/j4+P/4yMjP+Iior/hoeG/4ODg/+AgID/fHx8/3h4
+ eP90dHP/cXFx/3Jycv9lZWX/Tk9O/ycnJ/8iIiL/IyQj/yQkJP8jIyP/IyMj/yMhI/8ODg7/Dg4OZg4O
+ DlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAG5ubf9LS0z/S0xL/0tLS/9JSUn/RkZG/0A/
+ P/+Mi4z/s7Oz/6Ojo/+ioqL/oKCg/56env+cnJz/mZqZ/5eWl/+UlJT/kJGR/46Ojv+Li4v/h4eH/4OD
+ g/+Af4D/fHx8/3h4eP91dHT/cHBw/29vb/9wcHD/ZWVl/zAwMP8iIiL/IyMj/yQkJP8kJCT/JCMk/yMk
+ I/8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAHBwb/9NTU3/TU1N/0xM
+ TP9KSkr/R0dH/z8+P/+Ojo7/q6ur/6mpqf+np6b/paSk/6Kiov+goKD/nZ6e/5ubm/+YmJj/lZSU/5GR
+ kf+Ojo7/ioqL/4eHh/+Dg4P/f39//3x8fP93d3f/c3Nz/29vb/9vb2//cnJy/y8vL/8gISD/IyMj/yUk
+ JP8kJCT/JCQk/yQkJP8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAHFx
+ cf9OTk7/Tk5P/01NTf9MTEz/SEhI/0BAQP+QkJD/sLCv/62trf+srKv/qamp/6enp/+kpKX/oaKh/5+f
+ n/+cnJz/mJiY/5WVlf+RkZL/jo6O/4qKiv+Ghob/goKC/35+fv96env/dnZ2/3Fycf9vb2//cnJy/y8u
+ Lv8hICH/IyMj/yQkJf8lJSX/JCQl/yUlJP8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAHNzc/9PT0//T09P/09PT/9NTUz/SUlJ/0FAQf+SkpL/tbS0/7Gxsf+vr7D/rq6u/6ur
+ q/+pqan/pqWl/6Kiov+fn5//nJyc/5iZmP+UlZX/kZGR/42Njf+JiYn/hYWF/4GBgf99fX3/eXl5/3R0
+ dP9wcHD/cnJy/y4uLv8hISD/JCQk/yUlJf8mJSb/JiUl/yUlJf8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAHR0dP9RUVH/UVBR/09PT/9OTk7/S0pK/0JCQv+VlZX/uLi4/7a1
+ tf+zs7P/sbGx/6+vr/+tra3/qaqq/6ampv+ioqP/n5+f/5ycnP+YmJj/lJSU/5CQj/+MjIz/iIiI/4OD
+ g/9/f3//e3t7/3d3dv9ycnL/cnJy/y4vL/8hISH/JCQk/yYmJf8mJib/JiYl/yYlJf8ODg7/Dg4OZg4O
+ DlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAHV1df9TU1T/U1NT/1BRUf9PTk7/TExM/0JC
+ Qv+Xl5f/vr6+/7q6uv+3uLf/tbW1/7Kysv+wsLD/rq2t/6uqrP+mp6b/oqKi/5+fn/+bm5v/l5aX/5KS
+ kv+Oj47/i4qK/4aGhv+BgoH/fX5+/3l5ef90dHT/c3Nz/y8vL/8jISP/JCQk/yYmJv8nJif/JiYm/yYm
+ Jv8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAHZ3dv9VVVX/VVVV/1NS
+ Uv9QUFD/TU1N/0RERP+ampr/wsLC/76/v/+8vLz/ubm6/7a2t/+zs7P/ra2t/6ampv+io6P/np6f/5ub
+ mv+Wl5f/k5OS/46Ojv+Njo3/jY2N/4mJiP+Eg4P/f39//3t7e/92d3b/dXV0/y8vL/8hISH/JCUl/yYm
+ Jv8nJyf/JyYm/yYnJv8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAHh3
+ eP9WVlb/VlZW/1RUVP9RUVH/Tk5O/0VERP+cnJz/xsbG/8LCw//AwMD/vb69/7q7uv+3t7f/sLCw/6mp
+ qf+mpqb/oqGi/52dnf+ZmZn/lZWV/5SUlP+Tk5P/j4+P/4uLi/+Ghob/gYGB/319ff94eHj/dnd2/y8v
+ L/8hIiP/JSUl/ycnJv8oJyj/KCcn/ycnJ/8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAHl5ef9YWFj/V1dX/1ZWVv9SU1P/T09P/0ZGRv+fn5//ysvK/8bGxv/DxMT/wcHB/729
+ vv+6urr/s7Oz/6ysrP+oqKj/pKWk/6CgoP+bm5v/l5eX/5OTk/+SkpL/kJGQ/42Njf+IiIj/g4OD/35/
+ f/96env/eHh4/zAwL/8iIiL/JiYl/ycnJ/8oKCj/Jycn/ygnJ/8ODg7/Dg4OZg4ODlkNDQ0zBwcHDgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAHp7e/9ZWVr/WVlZ/1dXV/9UVFX/T1BP/0ZGRv+ioaL/z8/P/8rL
+ yv/HyMf/xMTE/8HBwf++vb7/tra2/6+vr/+qq6v/p6en/6Kiov+enp7/mZmZ/5WVlf+UlJT/k5KS/46O
+ jv+Kior/hYWF/4CAgP98fHz/eHl6/zAwMP8jIiP/JiYm/ygnKP8oKCr/KCgo/ycoKP8PDw//Dg4OZg4O
+ DlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAHx8fP9bW1r/Wlpa/1hYWP9VVlb/UFBQ/0dH
+ R/+kpKT/0tLS/87Ozv/Ly8v/x8fH/8PExP/AwMD/ubm5/7Kysf+tra3/qaio/6Wlpf+goKD/m5ub/5eW
+ l/+ZmZr/lJSU/5CQj/+Li4v/hoaG/4GBgf99fX3/e3t7/zAwMP8jIyP/JiYm/ygoJ/8pKSj/KSgo/ygo
+ KP8QEBD/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAH5+ff9cXFz/XFtc/1pZ
+ Wf9XV1b/UVFR/0hISP+lpaX/1tbW/9HR0f/Ozs7/y8rK/8bGxv/DwsL/uLi3/6ysrP+nqaf/o6Oi/56e
+ nv+ioqL/paWl/5+fn/+bmpv/lZaW/5GRkP+NjYz/iIiH/4KCgv9+fn7/fHx8/zEyMv8jIyP/Jicn/ygo
+ KP8pKSn/KCgp/ygpKP8RERH/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAH9/
+ f/9dXV3/XV1d/1paW/9YWFf/UlJS/0lJSf+kpKT/2tra/9TU1P/Q0ND/zc3N/8jJyf/ExMT/vb29/7W1
+ tv+xsbH/rKys/6ioqP+ioqT/nZ2e/5iYmP+YmJj/l5eX/5KSkv+Ojo3/iImI/4ODg/9/f3//fX19/zQ0
+ NP8jIyP/Jycn/ygoKP8pKSn/KSkp/ygoKP8TExP/Dg4OZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAICAgP9eXl7/Xl5e/1xcXP9ZWVn/U1NT/0lJSf+kpKT/3d3d/9fX1v/S0tL/z8/P/8vL
+ y//Gxsb/wsLC/72+vv+4uLn/tLS0/7CwsP+srKz/p6em/6Ghof+dnZ3/mJiY/5KTk/+Ojo7/iYmJ/4SE
+ hP9/gID/fn5+/zY2Nv8kIyT/Jycn/ygoKP8pKSn/KSkp/ykpKf8WFhb/DQ0NZg4ODlkNDQ0zBwcHDgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAIKCgv9fX17/Xl5e/11cXf9ZWln/VFRU/0pJSv+lpaX/4eHg/9na
+ 2v/V1dT/0NDQ/83Mzf/Hx8f/w8PD/7++vv+6urr/tbW1/7CwsP+sra3/p6en/6Kiov+enZ3/mZmY/5SU
+ k/+Pj4//ioqK/4WFhf+AgID/fX19/zk5Of8jIyT/Jycn/ygoKf8pKSn/KSkp/ykpJ/8YFxj/DQ0NZg4O
+ DlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAIOEhP9gYGD/X19f/15dXf9aWlr/VVVV/0tK
+ S/+lpaX/4eLi/9vb2//W1tX/0dHR/83Nzf/IyMj/w8PE/7+/v/+6u7r/tbW1/7Gxsf+tra3/qKio/6Kj
+ o/+enp7/mZmZ/5SUlP+Pj4//i4qK/4WFhf+AgID/fn59/zw8PP8kJCT/Jycn/ykpKf8qKin/KSkp/ygn
+ KP8ZGRr/DQ0NZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAISEhP9gYGD/X19f/15e
+ Xv9aWlv/VlZW/0tLS/+lpaX/4uLi/9zc3P/W19b/0dLR/83Ozv/JyMn/xMTE/7/AwP+7urv/trW2/7Gx
+ sf+tra3/qKin/6Ojov+enp7/mZmZ/5SUlP+Pj5D/i4qK/4aFhf+AgID/fn5+/z9AQP8lJSX/KCgn/ykp
+ Kf8qKin/KSkp/ygoKP8bGxv/DQ0NZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAIWH
+ h/9gYGD/X19f/15eXv9aWlv/VlZX/0xMTP+mpqb/4eLh/9vb2//W1tb/0dHR/83Nzf/IyMn/xMTE/7+/
+ v/+7u7v/tba1/7Gxsf+tra3/qKio/6Ojo/+enp7/mZmZ/5SUlP+Pj4//ioqK/4WFhf+AgID/fX59/0JC
+ Qv8mJib/KCgo/ykpKf8qKir/KSkp/ygoKP8cHBz/DQ0NZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAIiIiP9gYGD/X19f/15eXv9bW1v/WFdX/05OTf+np6f/4eHh/9rZ2v/V1dX/0NDQ/83N
+ zf/IyMf/w8PD/76/v/+6urr/tbW1/7CxsP+sra3/p6in/6Kiov+enp7/mZmZ/5OUlP+Pj4//ioqK/4WE
+ hf+AgID/fn19/0ZGRv8mJyb/Kikq/yorKv8qKyr/KSkp/ygoKP8dHh7/DQ0NZg4ODlkNDQ0zBwcHDgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAImJif9gYGD/X19f/15eXv9bW1v/WFhY/1BQUP+pqan/6Ojo/9bW
+ 1v/S09P/z8/P/8vLy//Gxsb/wsLC/76+vv+5ubn/tLS0/7CwsP+srKv/p6em/6Giov+dnZ3/mJiY/5OT
+ k/+Oj47/iYmJ/4SEhP9/f4D/e3t7/0pKS/8oKCj/Kysr/ywsLP8rKir/Kikq/yknJ/8fHx//DQ0NZg4O
+ DlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAIuLi/9fX17/Xl5f/11dXf9bW1v/WVhY/1RU
+ VP9XV1j//////+Pj4//T09P/z8/P/8rKyv/Fx8f/wcHC/7++v/+5ubn/tbW1/7CwsP+sraz/pqao/6Ki
+ ov+enZ7/mZmZ/5STlP+QkJD/i4uL/4aGhv+BgYH/fHx8/zEwL/8rKiz/LCws/y0sLP8rKir/F4GW/ygm
+ J/8iIiL/DQ0NZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAIyMjP9eXV3/Xl5e/11c
+ XP9bW1v/WFlZ/1ZWVf9OTk7/VldW/6enp/+lpaX/pKSk/6Kiov+goKD/nJyc/5iYmP+Tk5P/jo+P/4mJ
+ if+FhIX/gICA/3t7fP92dnb/cXJx/21tbf9nZmb/YmJi/11dXf9aWlr/MzMz/ywtLP8uLi3/LS0t/y0t
+ Lf8sKin/KScm/ycmJP8kJCT/DQ0NZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAI6O
+ jv9cXlz/Xl5e/1tbXP9aWlr/WFhY/1ZWV/9SU1P/Tk9P/0tLSv9HR0f/RERE/0JCQv9AQED/Pj8//zw8
+ Pf87Ozv/Ozs8/zo6Ov85OTn/ODg4/zY2Nv81NDX/NDM0/zMzM/8xMTH/MDAw/y8vL/8vLy//Li4u/y8v
+ L/8uLy7/Li0t/y0tLP8rKij/F4GW/ygmJ/8mJib/DQ0NZg4ODlkNDQ0zBwcHDgAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJCPkP9dW1v/XV1c/1tbW/9ZWVn/WFhY/1ZWVv9TVFP/UlJR/09PT/9OTk3/S0xL/0pK
+ Sv9ISEj/R0ZH/0VERf9CQkP/QUFC/0BAQP8/Pz//Pj4+/z09Pf87Ozv/OTk6/zg4OP82Njf/NTU1/zMz
+ M/8yMjL/MTEx/y8wL/8vLy//Ly0t/xeAlf8sKCf/KScm/ykmJf8nJyf/DQ0NZg4ODlkNDQ0zBwcHDgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAJKSkv9aWlr/W1tb/1paWv9ZWVj/V1dX/1ZVVv9UVFT/UlJR/1BP
+ UP9OTk7/TU1N/0xMTP9KSkr/SElI/0dHR/9GRkb/RERE/0JCQv9AQED/Pz8//z4+Pv89PT3/Ozs7/zk5
+ Of84ODj/Nzc2/zQ0NP8zMzP/MjIy/zAwMP8vLy//Lyws/y4qK/8tKCf/GI6q/ygnJv8pKCn/DQ0NZA4O
+ DlcNDQ0yCAgIDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAJOTk/9ZWFj/Wlpa/1lZWf9YWFj/V1dW/1VV
+ VP9TU1P/UVFR/1BPUP9PT0//TU5O/0xMTP9LSkv/SUlJ/0hISP9GRkb/RERE/0NCQv9BQUH/QD8//z4/
+ Pv89PT7/Ozw8/zo6Ov85OTn/Nzg3/zU1NP8zMzP/MTIy/zAwMP8vLy//Li0t/xeAlf8tJyj/KyYm/ygk
+ Jf8rKyv/DQ0NVw0NDUwNDQ0sCQkJDAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAJOTk/9XV1f/WVhY/1hY
+ V/9XV1f/VlZW/1VVVf9SUlL/UFFR/09PT/9OTk7/TU1N/0xMTP9LSkr/SUlJ/0dHR/9GRkb/REVE/0JC
+ Qv9BQUD/Pz8//z8/Pv89PT3/Ozw8/zo6Ov84ODj/Nzc2/zQ0Nf8zMzP/MTIy/zAwL/8vLy//Li0t/y0s
+ LP8rKSj/GI6q/yclJf8tLS3/DAwMMg0NDSwLCwsaCAgIBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKS
+ kv9UVVX/VVVV/1RVVf9TU1P/UlJS/1FRUf9PT0//Tk5O/01NTf9MTEz/SktL/0tJSf9JSUn/SEhI/0ZG
+ R/9FRUX/Q0ND/0FBQf9APz//Pj4+/z0+Pf88PDz/Ojo6/zk5Of84ODj/NjY2/zM0M/8yMjH/MDAw/y8v
+ L/8uLi7/LS0t/y0tLf8rKSn/KSYm/yclJP8vLy//BwcHDgkJCQwICAgHAAAAAgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJaVlf+TkpL/kpKS/4+Qj/+NjY3/iYmJ/4eHhv+FhYX/goKD/3+Af/99fHz/enl5/3Z2
+ dv90dHT/cnJy/3Bwb/9ra2v/aGho/2VmZf9jZGP/YWFh/15eX/9cXFz/WFhY/1VUVf9TUlL/UFBQ/01N
+ Tf9LS0v/SEhI/0NEQ/9BQUH/Pz8//zw9PP85OTn/NjY2/zIyMv8xMTH/AAAAAQAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD///////8AAP///////wAA////////AAD///////8AAP///////wAA+AAAAAAfAAD4AAAAAB8AAPgA
+ AAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+ AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgA
+ AAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+ AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgA
+ AAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAP///////wAA////////
+ AAD///////8AAP///////wAA////////AAA=
+
+
\ No newline at end of file
diff --git a/LibreHardwareMonitor/Utilities/HttpServer.cs b/LibreHardwareMonitor/Utilities/HttpServer.cs
index 0ca8f2e..02b1280 100644
--- a/LibreHardwareMonitor/Utilities/HttpServer.cs
+++ b/LibreHardwareMonitor/Utilities/HttpServer.cs
@@ -5,19 +5,22 @@
// All Rights Reserved.
using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
using System.Drawing;
using System.Drawing.Imaging;
+using System.Globalization;
using System.IO;
+using System.IO.Compression;
+using System.Linq;
using System.Net;
using System.Reflection;
+using System.Security.Cryptography;
using System.Text;
using System.Threading;
-using LibreHardwareMonitor.UI;
-using LibreHardwareMonitor.Hardware;
using System.Web;
-using System.Collections.Specialized;
-using System.Collections.Generic;
-using System.Globalization;
+using LibreHardwareMonitor.Hardware;
+using LibreHardwareMonitor.UI;
using Newtonsoft.Json.Linq;
namespace LibreHardwareMonitor.Utilities
@@ -25,13 +28,16 @@ namespace LibreHardwareMonitor.Utilities
public class HttpServer
{
private readonly HttpListener _listener;
- private Thread _listenerThread;
private readonly Node _root;
+ private Thread _listenerThread;
- public HttpServer(Node node, int port)
+ public HttpServer(Node node, int port, bool authEnabled = false, string userName = "", string password = "")
{
_root = node;
ListenerPort = port;
+ AuthEnabled = authEnabled;
+ UserName = userName;
+ Password = password;
try
{
@@ -43,27 +49,52 @@ namespace LibreHardwareMonitor.Utilities
}
}
+ ~HttpServer()
+ {
+ if (PlatformNotSupported)
+ return;
+
+
+ StopHttpListener();
+ _listener.Abort();
+ }
+
+ public bool AuthEnabled { get; set; }
+
+ public int ListenerPort { get; set; }
+
+ public string Password
+ {
+ get { return PasswordSHA256; }
+ set { PasswordSHA256 = ComputeSHA256(value); }
+ }
+
public bool PlatformNotSupported
{
- get
- {
- return _listener == null;
- }
+ get { return _listener == null; }
}
+ public string UserName { get; set; }
+
+ private string PasswordSHA256 { get; set; }
+
public bool StartHttpListener()
{
if (PlatformNotSupported)
return false;
+
try
{
if (_listener.IsListening)
return true;
+
string prefix = "http://+:" + ListenerPort + "/";
_listener.Prefixes.Clear();
_listener.Prefixes.Add(prefix);
+ _listener.Realm = "Libre Hardware Monitor";
+ _listener.AuthenticationSchemes = AuthEnabled ? AuthenticationSchemes.Basic : AuthenticationSchemes.Anonymous;
_listener.Start();
if (_listenerThread == null)
@@ -85,13 +116,14 @@ namespace LibreHardwareMonitor.Utilities
if (PlatformNotSupported)
return false;
+
try
{
_listenerThread?.Abort();
_listener.Stop();
_listenerThread = null;
}
- catch (HttpListenerException)
+ catch (HttpListenerException)
{ }
catch (ThreadAbortException)
{ }
@@ -99,6 +131,7 @@ namespace LibreHardwareMonitor.Utilities
{ }
catch (Exception)
{ }
+
return true;
}
@@ -118,6 +151,7 @@ namespace LibreHardwareMonitor.Utilities
{
dict.Add(k, col[k]);
}
+
return dict;
}
@@ -137,6 +171,7 @@ namespace LibreHardwareMonitor.Utilities
return s;
}
}
+
return null;
}
@@ -146,6 +181,7 @@ namespace LibreHardwareMonitor.Utilities
{
throw new ArgumentException("Specified sensor '" + sNode.Sensor.Identifier + "' can not be set");
}
+
if (value == "null")
{
sNode.Sensor.Control.SetDefault();
@@ -218,7 +254,7 @@ namespace LibreHardwareMonitor.Utilities
private string HandlePostRequest(HttpListenerRequest request)
{
JObject result = new JObject { ["result"] = "ok" };
-
+
try
{
if (request.Url.Segments.Length == 2)
@@ -243,7 +279,7 @@ namespace LibreHardwareMonitor.Utilities
#if DEBUG
return result.ToString(Newtonsoft.Json.Formatting.Indented);
#else
- return result.ToString(Newtonsoft.Json.Formatting.None);
+ return result.ToString(Newtonsoft.Json.Formatting.None);
#endif
}
@@ -253,6 +289,7 @@ namespace LibreHardwareMonitor.Utilities
if (listener == null || !listener.IsListening)
return;
+
// Call EndGetContext to complete the asynchronous operation.
HttpListenerContext context;
try
@@ -266,66 +303,123 @@ namespace LibreHardwareMonitor.Utilities
HttpListenerRequest request = context.Request;
- if (request.HttpMethod == "POST")
+ bool authenticated;
+
+ if (AuthEnabled)
{
- string postResult = HandlePostRequest(request);
-
- Stream output = context.Response.OutputStream;
- byte[] utfBytes = Encoding.UTF8.GetBytes(postResult);
-
- context.Response.AddHeader("Cache-Control", "no-cache");
- context.Response.ContentLength64 = utfBytes.Length;
- context.Response.ContentType = "application/json";
-
- output.Write(utfBytes, 0, utfBytes.Length);
- output.Close();
- }
- else if (request.HttpMethod == "GET")
- {
- string requestedFile = request.RawUrl.Substring(1);
-
- if (requestedFile == "data.json")
+ try
{
- SendJson(context.Response);
- return;
+ HttpListenerBasicIdentity identity = (HttpListenerBasicIdentity)context.User.Identity;
+ authenticated = (identity.Name == UserName) & (ComputeSHA256(identity.Password) == Password);
}
-
- if (requestedFile.Contains("images_icon"))
+ catch
{
- ServeResourceImage(context.Response,
- requestedFile.Replace("images_icon/", string.Empty));
- return;
+ authenticated = false;
}
-
- // default file to be served
- if (string.IsNullOrEmpty(requestedFile))
- requestedFile = "index.html";
-
- string[] splits = requestedFile.Split('.');
- string ext = splits[splits.Length - 1];
- ServeResourceFile(context.Response, "Web." + requestedFile.Replace('/', '.'), ext);
}
else
{
- context.Response.StatusCode = 404;
+ authenticated = true;
+ }
+
+ if (authenticated)
+ {
+ switch (request.HttpMethod)
+ {
+ case "POST":
+ {
+ string postResult = HandlePostRequest(request);
+
+ Stream output = context.Response.OutputStream;
+ byte[] utfBytes = Encoding.UTF8.GetBytes(postResult);
+
+ context.Response.AddHeader("Cache-Control", "no-cache");
+ context.Response.ContentLength64 = utfBytes.Length;
+ context.Response.ContentType = "application/json";
+
+ output.Write(utfBytes, 0, utfBytes.Length);
+ output.Close();
+
+ break;
+ }
+ case "GET":
+ {
+ string requestedFile = request.RawUrl.Substring(1);
+
+ if (requestedFile == "data.json")
+ {
+ SendJson(context.Response, request);
+ return;
+ }
+
+ if (requestedFile.Contains("images_icon"))
+ {
+ ServeResourceImage(context.Response,
+ requestedFile.Replace("images_icon/", string.Empty));
+
+ return;
+ }
+
+ // default file to be served
+ if (string.IsNullOrEmpty(requestedFile))
+ requestedFile = "index.html";
+
+ string[] splits = requestedFile.Split('.');
+ string ext = splits[splits.Length - 1];
+ ServeResourceFile(context.Response, "Web." + requestedFile.Replace('/', '.'), ext);
+
+ break;
+ }
+ default:
+ {
+ context.Response.StatusCode = 404;
+ break;
+ }
+ }
+ }
+ else
+ {
+ context.Response.StatusCode = 401;
+ }
+
+ if (context.Response.StatusCode == 401)
+ {
+ const string responseString = @"401 Unauthorized
+ 401 Unauthorized
+ Authorization required. ";
+
+ byte[] buffer = Encoding.UTF8.GetBytes(responseString);
+ context.Response.ContentLength64 = buffer.Length;
+ context.Response.StatusCode = 401;
+ Stream output = context.Response.OutputStream;
+ output.Write(buffer, 0, buffer.Length);
+ output.Close();
+ }
+
+ try
+ {
context.Response.Close();
}
+ catch
+ {
+ // client closed connection before the content was sent
+ }
}
private void ServeResourceFile(HttpListenerResponse response, string name, string ext)
{
// resource names do not support the hyphen
name = "LibreHardwareMonitor.Resources." +
- name.Replace("custom-theme", "custom_theme");
+ name.Replace("custom-theme", "custom_theme");
string[] names =
- Assembly.GetExecutingAssembly().GetManifestResourceNames();
+ Assembly.GetExecutingAssembly().GetManifestResourceNames();
+
for (int i = 0; i < names.Length; i++)
{
if (names[i].Replace('\\', '.') == name)
{
- using (Stream stream = Assembly.GetExecutingAssembly().
- GetManifestResourceStream(names[i]))
+ using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(names[i]))
{
response.ContentType = GetContentType("." + ext);
response.ContentLength64 = stream.Length;
@@ -338,16 +432,16 @@ namespace LibreHardwareMonitor.Utilities
{
output.Write(buffer, 0, len);
}
+
output.Flush();
output.Close();
response.Close();
}
catch (HttpListenerException)
- {
- }
+ { }
catch (InvalidOperationException)
- {
- }
+ { }
+
return;
}
}
@@ -367,10 +461,8 @@ namespace LibreHardwareMonitor.Utilities
{
if (names[i].Replace('\\', '.') == name)
{
- using (Stream stream = Assembly.GetExecutingAssembly().
- GetManifestResourceStream(names[i]))
+ using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(names[i]))
{
-
Image image = Image.FromStream(stream);
response.ContentType = "image/png";
try
@@ -381,11 +473,12 @@ namespace LibreHardwareMonitor.Utilities
image.Save(ms, ImageFormat.Png);
ms.WriteTo(output);
}
+
output.Close();
}
catch (HttpListenerException)
- {
- }
+ { }
+
image.Dispose();
response.Close();
return;
@@ -397,7 +490,7 @@ namespace LibreHardwareMonitor.Utilities
response.Close();
}
- private void SendJson(HttpListenerResponse response)
+ private void SendJson(HttpListenerResponse response, HttpListenerRequest request = null)
{
JObject json = new JObject();
@@ -419,20 +512,42 @@ namespace LibreHardwareMonitor.Utilities
#endif
byte[] buffer = Encoding.UTF8.GetBytes(responseContent);
- response.AddHeader("Cache-Control", "no-cache");
- response.AddHeader("Access-Control-Allow-Origin", "*");
- response.ContentLength64 = buffer.Length;
- response.ContentType = "application/json";
-
+ bool acceptGzip;
try
{
+ acceptGzip = (request != null) && (request.Headers["Accept-Encoding"].ToLower().IndexOf("gzip", StringComparison.OrdinalIgnoreCase) >= 0);
+ }
+ catch
+ {
+ acceptGzip = false;
+ }
+
+ if (acceptGzip)
+ response.AddHeader("Content-Encoding", "gzip");
+
+ response.AddHeader("Cache-Control", "no-cache");
+ response.AddHeader("Access-Control-Allow-Origin", "*");
+ response.ContentType = "application/json";
+ try
+ {
+ if (acceptGzip)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var zip = new GZipStream(ms, CompressionMode.Compress, true))
+ zip.Write(buffer, 0, buffer.Length);
+
+ buffer = ms.ToArray();
+ }
+ }
+
+ response.ContentLength64 = buffer.Length;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
}
catch (HttpListenerException)
- {
- }
+ { }
response.Close();
}
@@ -448,13 +563,13 @@ namespace LibreHardwareMonitor.Utilities
["Max"] = string.Empty
};
- if (n is SensorNode)
+ if (n is SensorNode sensorNode)
{
- jsonNode["SensorId"] = ((SensorNode)n).Sensor.Identifier.ToString();
- jsonNode["Type"] = ((SensorNode)n).Sensor.SensorType.ToString();
- jsonNode["Min"] = ((SensorNode)n).Min;
- jsonNode["Value"] = ((SensorNode)n).Value;
- jsonNode["Max"] = ((SensorNode)n).Max;
+ jsonNode["SensorId"] = sensorNode.Sensor.Identifier.ToString();
+ jsonNode["Type"] = sensorNode.Sensor.SensorType.ToString();
+ jsonNode["Min"] = sensorNode.Min;
+ jsonNode["Value"] = sensorNode.Value;
+ jsonNode["Max"] = sensorNode.Max;
jsonNode["ImageURL"] = "images/transparent.png";
}
else if (n is HardwareNode hardwareNode)
@@ -506,7 +621,6 @@ namespace LibreHardwareMonitor.Utilities
private static string GetHardwareImageFile(HardwareNode hn)
{
-
switch (hn.Hardware.HardwareType)
{
case HardwareType.Cpu:
@@ -536,12 +650,10 @@ namespace LibreHardwareMonitor.Utilities
default:
return "cpu.png";
}
-
}
private static string GetTypeImageFile(TypeNode tn)
{
-
switch (tn.SensorType)
{
case SensorType.Voltage:
@@ -567,18 +679,16 @@ namespace LibreHardwareMonitor.Utilities
default:
return "power.png";
}
-
}
- public int ListenerPort { get; set; }
-
- ~HttpServer()
+ private string ComputeSHA256(string text)
{
- if (PlatformNotSupported)
- return;
-
- StopHttpListener();
- _listener.Abort();
+ using (SHA256 hash = SHA256.Create())
+ {
+ return string.Concat(hash
+ .ComputeHash(Encoding.UTF8.GetBytes(text))
+ .Select(item => item.ToString("x2")));
+ }
}
public void Quit()
@@ -586,6 +696,7 @@ namespace LibreHardwareMonitor.Utilities
if (PlatformNotSupported)
return;
+
StopHttpListener();
_listener.Abort();
}
diff --git a/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGroup.cs b/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGroup.cs
index 00282fb..795b35b 100644
--- a/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGroup.cs
+++ b/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGroup.cs
@@ -57,7 +57,6 @@ namespace LibreHardwareMonitor.Hardware.Gpu
NvApi.NvDisplayHandle displayHandle = new NvApi.NvDisplayHandle();
status = NvApi.NvAPI_EnumNvidiaDisplayHandle(i, ref displayHandle);
i++;
- NvApi.NvDisplayHandle a;
if (status == NvApi.NvStatus.OK)
{
diff --git a/LibreHardwareMonitorLib/Hardware/Storage/DebugSmart.cs b/LibreHardwareMonitorLib/Hardware/Storage/DebugSmart.cs
index c0b8355..ba10355 100644
--- a/LibreHardwareMonitorLib/Hardware/Storage/DebugSmart.cs
+++ b/LibreHardwareMonitorLib/Hardware/Storage/DebugSmart.cs
@@ -4,10 +4,13 @@
// Partial Copyright (C) Michael Möller and Contributors.
// All Rights Reserved.
-namespace LibreHardwareMonitor.Hardware.Storage
-{
#if DEBUG
+using System;
+using LibreHardwareMonitor.Interop;
+
+namespace LibreHardwareMonitor.Hardware.Storage
+{
internal class DebugSmart : ISmart
{
private readonly Drive[] _drives = {
@@ -376,7 +379,7 @@ namespace LibreHardwareMonitor.Hardware.Storage
string[] lines = value.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
DriveAttributeValues = new Kernel32.SMART_ATTRIBUTE[lines.Length];
- var thresholds = new List();
+ var thresholds = new System.Collections.Generic.List();
for (int i = 0; i < lines.Length; i++)
{
@@ -416,6 +419,6 @@ namespace LibreHardwareMonitor.Hardware.Storage
public string Name { get; }
}
}
+}
#endif
-}