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 -}