mirror of
https://github.com/Ylianst/MeshCentralRouter
synced 2025-12-06 00:13:33 +00:00
Merge branch 'master' into proxy
This commit is contained in:
1
AddPortMapForm.Designer.cs
generated
1
AddPortMapForm.Designer.cs
generated
@@ -138,7 +138,6 @@
|
||||
resources.GetString("appComboBox.Items4"),
|
||||
resources.GetString("appComboBox.Items5")});
|
||||
this.appComboBox.Name = "appComboBox";
|
||||
this.appComboBox.Sorted = true;
|
||||
this.appComboBox.SelectedIndexChanged += new System.EventHandler(this.appComboBox_SelectedIndexChanged);
|
||||
//
|
||||
// label5
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@ limitations under the License.
|
||||
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MeshCentralRouter
|
||||
{
|
||||
@@ -43,13 +44,25 @@ namespace MeshCentralRouter
|
||||
if (x == 3) { return 4; } // PuTTY
|
||||
if (x == 4) { return 3; } // RDP
|
||||
if (x == 5) { return 5; } // WinSCP
|
||||
return x;
|
||||
return 0;
|
||||
}
|
||||
public string getAppIdStr()
|
||||
{
|
||||
int x = (int)appComboBox.SelectedIndex;
|
||||
if (x < 6) { return null; } // Custom or pre-defined
|
||||
return apps[x - 6][1];
|
||||
}
|
||||
public NodeClass getNode() { return (NodeClass)nodeComboBox.SelectedItem; }
|
||||
public void setNode(NodeClass node) { selectedNode = node; }
|
||||
|
||||
private List<String[]> apps = null;
|
||||
|
||||
private void AddPortMapForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
// Add any custom applications
|
||||
apps = Settings.GetApplications();
|
||||
if (apps != null) { foreach (String[] app in apps) { appComboBox.Items.Add(app[0]); } }
|
||||
|
||||
if (selectedNode == null)
|
||||
{
|
||||
// Fill the groups
|
||||
|
||||
1
AddRelayMapForm.Designer.cs
generated
1
AddRelayMapForm.Designer.cs
generated
@@ -140,7 +140,6 @@
|
||||
resources.GetString("appComboBox.Items4"),
|
||||
resources.GetString("appComboBox.Items5")});
|
||||
this.appComboBox.Name = "appComboBox";
|
||||
this.appComboBox.Sorted = true;
|
||||
this.appComboBox.SelectedIndexChanged += new System.EventHandler(this.appComboBox_SelectedIndexChanged);
|
||||
//
|
||||
// label5
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Windows.Forms;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MeshCentralRouter
|
||||
{
|
||||
@@ -46,13 +47,25 @@ namespace MeshCentralRouter
|
||||
if (x == 3) { return 4; } // PuTTY
|
||||
if (x == 4) { return 3; } // RDP
|
||||
if (x == 5) { return 5; } // WinSCP
|
||||
return x;
|
||||
return 0;
|
||||
}
|
||||
public string getAppIdStr()
|
||||
{
|
||||
int x = (int)appComboBox.SelectedIndex;
|
||||
if (x < 6) { return null; } // Custom or pre-defined
|
||||
return apps[x - 6][1];
|
||||
}
|
||||
public NodeClass getNode() { return (NodeClass)nodeComboBox.SelectedItem; }
|
||||
public void setNode(NodeClass node) { selectedNode = node; }
|
||||
|
||||
private List<String[]> apps = null;
|
||||
|
||||
private void AddRelayMapForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
// Add any custom applications
|
||||
apps = Settings.GetApplications();
|
||||
if (apps != null) { foreach (String[] app in apps) { appComboBox.Items.Add(app[0]); } }
|
||||
|
||||
if (selectedNode == null)
|
||||
{
|
||||
// Fill the groups
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
234
CustomAppsAddForm.Designer.cs
generated
Normal file
234
CustomAppsAddForm.Designer.cs
generated
Normal file
@@ -0,0 +1,234 @@
|
||||
namespace MeshCentralRouter
|
||||
{
|
||||
partial class CustomAppsAddForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CustomAppsAddForm));
|
||||
this.okButton = new System.Windows.Forms.Button();
|
||||
this.cancelButton = new System.Windows.Forms.Button();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.nameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.protocolTextBox = new System.Windows.Forms.TextBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.commandTextBox = new System.Windows.Forms.TextBox();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.selectFileButton = new System.Windows.Forms.Button();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
this.argsTextBox = new System.Windows.Forms.TextBox();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// okButton
|
||||
//
|
||||
this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.okButton.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.okButton.Location = new System.Drawing.Point(244, 190);
|
||||
this.okButton.Name = "okButton";
|
||||
this.okButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.okButton.TabIndex = 4;
|
||||
this.okButton.Text = "OK";
|
||||
this.okButton.UseVisualStyleBackColor = true;
|
||||
this.okButton.Click += new System.EventHandler(this.okButton_Click);
|
||||
//
|
||||
// cancelButton
|
||||
//
|
||||
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.cancelButton.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.cancelButton.Location = new System.Drawing.Point(325, 190);
|
||||
this.cancelButton.Name = "cancelButton";
|
||||
this.cancelButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.cancelButton.TabIndex = 5;
|
||||
this.cancelButton.Text = "Cancel";
|
||||
this.cancelButton.UseVisualStyleBackColor = true;
|
||||
this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(6, 22);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(35, 13);
|
||||
this.label1.TabIndex = 6;
|
||||
this.label1.Text = "Name";
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Location = new System.Drawing.Point(116, 19);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(266, 20);
|
||||
this.nameTextBox.TabIndex = 7;
|
||||
this.nameTextBox.TextChanged += new System.EventHandler(this.nameTextBox_TextChanged);
|
||||
//
|
||||
// protocolTextBox
|
||||
//
|
||||
this.protocolTextBox.Location = new System.Drawing.Point(116, 45);
|
||||
this.protocolTextBox.Name = "protocolTextBox";
|
||||
this.protocolTextBox.Size = new System.Drawing.Size(266, 20);
|
||||
this.protocolTextBox.TabIndex = 9;
|
||||
this.protocolTextBox.TextChanged += new System.EventHandler(this.nameTextBox_TextChanged);
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(6, 48);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(46, 13);
|
||||
this.label2.TabIndex = 8;
|
||||
this.label2.Text = "Protocol";
|
||||
//
|
||||
// commandTextBox
|
||||
//
|
||||
this.commandTextBox.Location = new System.Drawing.Point(116, 71);
|
||||
this.commandTextBox.Name = "commandTextBox";
|
||||
this.commandTextBox.Size = new System.Drawing.Size(238, 20);
|
||||
this.commandTextBox.TabIndex = 11;
|
||||
this.commandTextBox.TextChanged += new System.EventHandler(this.nameTextBox_TextChanged);
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(6, 74);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(85, 13);
|
||||
this.label3.TabIndex = 10;
|
||||
this.label3.Text = "Executable Path";
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.groupBox1.Controls.Add(this.label5);
|
||||
this.groupBox1.Controls.Add(this.argsTextBox);
|
||||
this.groupBox1.Controls.Add(this.selectFileButton);
|
||||
this.groupBox1.Controls.Add(this.nameTextBox);
|
||||
this.groupBox1.Controls.Add(this.label3);
|
||||
this.groupBox1.Controls.Add(this.commandTextBox);
|
||||
this.groupBox1.Controls.Add(this.label2);
|
||||
this.groupBox1.Controls.Add(this.protocolTextBox);
|
||||
this.groupBox1.Controls.Add(this.label1);
|
||||
this.groupBox1.Location = new System.Drawing.Point(12, 57);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(388, 127);
|
||||
this.groupBox1.TabIndex = 12;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "Application";
|
||||
//
|
||||
// selectFileButton
|
||||
//
|
||||
this.selectFileButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.selectFileButton.Location = new System.Drawing.Point(360, 71);
|
||||
this.selectFileButton.Name = "selectFileButton";
|
||||
this.selectFileButton.Size = new System.Drawing.Size(21, 20);
|
||||
this.selectFileButton.TabIndex = 12;
|
||||
this.selectFileButton.Text = "...";
|
||||
this.selectFileButton.UseVisualStyleBackColor = true;
|
||||
this.selectFileButton.Click += new System.EventHandler(this.selectFileButton_Click);
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.label4.Location = new System.Drawing.Point(12, 9);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(388, 45);
|
||||
this.label4.TabIndex = 13;
|
||||
this.label4.Text = "Enter a friendly name, protocol (like HTTP, RDP, VNC) and the command line and ar" +
|
||||
"guments to run the application. In the arguments, use %L for address, %P for con" +
|
||||
"nection port and %N for computer name.";
|
||||
//
|
||||
// openFileDialog
|
||||
//
|
||||
this.openFileDialog.DefaultExt = "exe";
|
||||
this.openFileDialog.Filter = "Executable|*.exe|All Files|*.*";
|
||||
this.openFileDialog.Title = "Select Application Executable";
|
||||
//
|
||||
// label5
|
||||
//
|
||||
this.label5.AutoSize = true;
|
||||
this.label5.Location = new System.Drawing.Point(6, 100);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(57, 13);
|
||||
this.label5.TabIndex = 13;
|
||||
this.label5.Text = "Arguments";
|
||||
//
|
||||
// argsTextBox
|
||||
//
|
||||
this.argsTextBox.Location = new System.Drawing.Point(116, 97);
|
||||
this.argsTextBox.Name = "argsTextBox";
|
||||
this.argsTextBox.Size = new System.Drawing.Size(265, 20);
|
||||
this.argsTextBox.TabIndex = 14;
|
||||
this.argsTextBox.TextChanged += new System.EventHandler(this.nameTextBox_TextChanged);
|
||||
//
|
||||
// CustomAppsAddForm
|
||||
//
|
||||
this.AcceptButton = this.okButton;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.cancelButton;
|
||||
this.ClientSize = new System.Drawing.Size(412, 225);
|
||||
this.Controls.Add(this.label4);
|
||||
this.Controls.Add(this.groupBox1);
|
||||
this.Controls.Add(this.okButton);
|
||||
this.Controls.Add(this.cancelButton);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "CustomAppsAddForm";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Add Custom Application";
|
||||
this.Load += new System.EventHandler(this.CustomAppsAddForm_Load);
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.groupBox1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Button okButton;
|
||||
private System.Windows.Forms.Button cancelButton;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.TextBox nameTextBox;
|
||||
private System.Windows.Forms.TextBox protocolTextBox;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.TextBox commandTextBox;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.Button selectFileButton;
|
||||
private System.Windows.Forms.OpenFileDialog openFileDialog;
|
||||
private System.Windows.Forms.Label label5;
|
||||
private System.Windows.Forms.TextBox argsTextBox;
|
||||
}
|
||||
}
|
||||
69
CustomAppsAddForm.cs
Normal file
69
CustomAppsAddForm.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MeshCentralRouter
|
||||
{
|
||||
public partial class CustomAppsAddForm : Form
|
||||
{
|
||||
public string appName
|
||||
{
|
||||
get { return nameTextBox.Text; }
|
||||
set { nameTextBox.Text = value; updateInfo(); }
|
||||
}
|
||||
public string appProtocol
|
||||
{
|
||||
get { return protocolTextBox.Text; }
|
||||
set { protocolTextBox.Text = value; updateInfo(); }
|
||||
}
|
||||
public string appCommand
|
||||
{
|
||||
get { return commandTextBox.Text; }
|
||||
set { commandTextBox.Text = value; updateInfo(); }
|
||||
}
|
||||
public string appArgs
|
||||
{
|
||||
get { return argsTextBox.Text; }
|
||||
set { argsTextBox.Text = value; updateInfo(); }
|
||||
}
|
||||
|
||||
public CustomAppsAddForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void updateInfo()
|
||||
{
|
||||
okButton.Enabled = (nameTextBox.Text.Length > 0) && (protocolTextBox.Text.Length > 0) && (commandTextBox.Text.Length > 0) && (nameTextBox.Text.IndexOf(' ') == -1) && (protocolTextBox.Text.IndexOf(' ') == -1) && (File.Exists(commandTextBox.Text));
|
||||
}
|
||||
|
||||
private void CustomAppsAddForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
updateInfo();
|
||||
nameTextBox.Focus();
|
||||
}
|
||||
|
||||
private void nameTextBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
updateInfo();
|
||||
}
|
||||
|
||||
private void okButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.OK;
|
||||
}
|
||||
|
||||
private void cancelButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.Cancel;
|
||||
}
|
||||
|
||||
private void selectFileButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (openFileDialog.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
commandTextBox.Text = openFileDialog.FileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1818
CustomAppsAddForm.resx
Normal file
1818
CustomAppsAddForm.resx
Normal file
File diff suppressed because it is too large
Load Diff
276
CustomAppsForm.Designer.cs
generated
Normal file
276
CustomAppsForm.Designer.cs
generated
Normal file
@@ -0,0 +1,276 @@
|
||||
namespace MeshCentralRouter
|
||||
{
|
||||
partial class CustomAppsForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CustomAppsForm));
|
||||
this.cancelButton = new System.Windows.Forms.Button();
|
||||
this.okButton = new System.Windows.Forms.Button();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.removeButton = new System.Windows.Forms.Button();
|
||||
this.addButton = new System.Windows.Forms.Button();
|
||||
this.mainListView = new System.Windows.Forms.ListView();
|
||||
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.appContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.runToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.removeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.addToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.editButton = new System.Windows.Forms.Button();
|
||||
this.runButton = new System.Windows.Forms.Button();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.appContextMenuStrip.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// cancelButton
|
||||
//
|
||||
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.cancelButton.Location = new System.Drawing.Point(320, 280);
|
||||
this.cancelButton.Name = "cancelButton";
|
||||
this.cancelButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.cancelButton.TabIndex = 0;
|
||||
this.cancelButton.Text = "Cancel";
|
||||
this.cancelButton.UseVisualStyleBackColor = true;
|
||||
this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
|
||||
//
|
||||
// okButton
|
||||
//
|
||||
this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.okButton.Location = new System.Drawing.Point(239, 280);
|
||||
this.okButton.Name = "okButton";
|
||||
this.okButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.okButton.TabIndex = 1;
|
||||
this.okButton.Text = "OK";
|
||||
this.okButton.UseVisualStyleBackColor = true;
|
||||
this.okButton.Click += new System.EventHandler(this.okButton_Click);
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.label1.Location = new System.Drawing.Point(12, 9);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(383, 48);
|
||||
this.label1.TabIndex = 2;
|
||||
this.label1.Text = "Setup custom applications that MeshCentral Router can open to use port mappings. " +
|
||||
"These applications match a protocol and have a command line to open the applicat" +
|
||||
"ion.";
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.groupBox1.Controls.Add(this.runButton);
|
||||
this.groupBox1.Controls.Add(this.editButton);
|
||||
this.groupBox1.Controls.Add(this.removeButton);
|
||||
this.groupBox1.Controls.Add(this.addButton);
|
||||
this.groupBox1.Controls.Add(this.mainListView);
|
||||
this.groupBox1.Location = new System.Drawing.Point(15, 60);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(380, 214);
|
||||
this.groupBox1.TabIndex = 3;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "Applications";
|
||||
//
|
||||
// removeButton
|
||||
//
|
||||
this.removeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.removeButton.Location = new System.Drawing.Point(299, 185);
|
||||
this.removeButton.Name = "removeButton";
|
||||
this.removeButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.removeButton.TabIndex = 2;
|
||||
this.removeButton.Text = "Remove";
|
||||
this.removeButton.UseVisualStyleBackColor = true;
|
||||
this.removeButton.Click += new System.EventHandler(this.removeButton_Click);
|
||||
//
|
||||
// addButton
|
||||
//
|
||||
this.addButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.addButton.Location = new System.Drawing.Point(218, 185);
|
||||
this.addButton.Name = "addButton";
|
||||
this.addButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.addButton.TabIndex = 1;
|
||||
this.addButton.Text = "Add";
|
||||
this.addButton.UseVisualStyleBackColor = true;
|
||||
this.addButton.Click += new System.EventHandler(this.addButton_Click);
|
||||
//
|
||||
// mainListView
|
||||
//
|
||||
this.mainListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.mainListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||
this.columnHeader1,
|
||||
this.columnHeader2,
|
||||
this.columnHeader3});
|
||||
this.mainListView.ContextMenuStrip = this.appContextMenuStrip;
|
||||
this.mainListView.FullRowSelect = true;
|
||||
this.mainListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
|
||||
this.mainListView.Location = new System.Drawing.Point(6, 19);
|
||||
this.mainListView.Name = "mainListView";
|
||||
this.mainListView.Size = new System.Drawing.Size(368, 160);
|
||||
this.mainListView.Sorting = System.Windows.Forms.SortOrder.Ascending;
|
||||
this.mainListView.TabIndex = 0;
|
||||
this.mainListView.UseCompatibleStateImageBehavior = false;
|
||||
this.mainListView.View = System.Windows.Forms.View.Details;
|
||||
this.mainListView.SelectedIndexChanged += new System.EventHandler(this.mainListView_SelectedIndexChanged);
|
||||
//
|
||||
// columnHeader1
|
||||
//
|
||||
this.columnHeader1.Text = "Name";
|
||||
//
|
||||
// columnHeader2
|
||||
//
|
||||
this.columnHeader2.Text = "Protocol";
|
||||
//
|
||||
// columnHeader3
|
||||
//
|
||||
this.columnHeader3.Text = "Command";
|
||||
this.columnHeader3.Width = 223;
|
||||
//
|
||||
// appContextMenuStrip
|
||||
//
|
||||
this.appContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.editToolStripMenuItem,
|
||||
this.runToolStripMenuItem,
|
||||
this.removeToolStripMenuItem,
|
||||
this.toolStripMenuItem1,
|
||||
this.addToolStripMenuItem});
|
||||
this.appContextMenuStrip.Name = "appContextMenuStrip";
|
||||
this.appContextMenuStrip.Size = new System.Drawing.Size(118, 98);
|
||||
this.appContextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(this.appContextMenuStrip_Opening);
|
||||
//
|
||||
// editToolStripMenuItem
|
||||
//
|
||||
this.editToolStripMenuItem.Name = "editToolStripMenuItem";
|
||||
this.editToolStripMenuItem.Size = new System.Drawing.Size(117, 22);
|
||||
this.editToolStripMenuItem.Text = "&Edit...";
|
||||
this.editToolStripMenuItem.Click += new System.EventHandler(this.editToolStripMenuItem_Click);
|
||||
//
|
||||
// runToolStripMenuItem
|
||||
//
|
||||
this.runToolStripMenuItem.Name = "runToolStripMenuItem";
|
||||
this.runToolStripMenuItem.Size = new System.Drawing.Size(117, 22);
|
||||
this.runToolStripMenuItem.Text = "R&un...";
|
||||
this.runToolStripMenuItem.Click += new System.EventHandler(this.runToolStripMenuItem_Click);
|
||||
//
|
||||
// removeToolStripMenuItem
|
||||
//
|
||||
this.removeToolStripMenuItem.Name = "removeToolStripMenuItem";
|
||||
this.removeToolStripMenuItem.Size = new System.Drawing.Size(117, 22);
|
||||
this.removeToolStripMenuItem.Text = "&Remove";
|
||||
this.removeToolStripMenuItem.Click += new System.EventHandler(this.removeButton_Click);
|
||||
//
|
||||
// toolStripMenuItem1
|
||||
//
|
||||
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
|
||||
this.toolStripMenuItem1.Size = new System.Drawing.Size(114, 6);
|
||||
//
|
||||
// addToolStripMenuItem
|
||||
//
|
||||
this.addToolStripMenuItem.Name = "addToolStripMenuItem";
|
||||
this.addToolStripMenuItem.Size = new System.Drawing.Size(117, 22);
|
||||
this.addToolStripMenuItem.Text = "&Add...";
|
||||
this.addToolStripMenuItem.Click += new System.EventHandler(this.addButton_Click);
|
||||
//
|
||||
// editButton
|
||||
//
|
||||
this.editButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.editButton.Location = new System.Drawing.Point(137, 185);
|
||||
this.editButton.Name = "editButton";
|
||||
this.editButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.editButton.TabIndex = 3;
|
||||
this.editButton.Text = "Edit...";
|
||||
this.editButton.UseVisualStyleBackColor = true;
|
||||
this.editButton.Click += new System.EventHandler(this.editToolStripMenuItem_Click);
|
||||
//
|
||||
// runButton
|
||||
//
|
||||
this.runButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.runButton.Location = new System.Drawing.Point(56, 185);
|
||||
this.runButton.Name = "runButton";
|
||||
this.runButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.runButton.TabIndex = 4;
|
||||
this.runButton.Text = "Run...";
|
||||
this.runButton.UseVisualStyleBackColor = true;
|
||||
this.runButton.Click += new System.EventHandler(this.runToolStripMenuItem_Click);
|
||||
//
|
||||
// CustomAppsForm
|
||||
//
|
||||
this.AcceptButton = this.okButton;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.cancelButton;
|
||||
this.ClientSize = new System.Drawing.Size(407, 315);
|
||||
this.Controls.Add(this.groupBox1);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.okButton);
|
||||
this.Controls.Add(this.cancelButton);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "CustomAppsForm";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Custom Applications";
|
||||
this.Load += new System.EventHandler(this.CustomAppsForm_Load);
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.appContextMenuStrip.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Button cancelButton;
|
||||
private System.Windows.Forms.Button okButton;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
private System.Windows.Forms.Button removeButton;
|
||||
private System.Windows.Forms.Button addButton;
|
||||
private System.Windows.Forms.ListView mainListView;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader1;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader2;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader3;
|
||||
private System.Windows.Forms.ContextMenuStrip appContextMenuStrip;
|
||||
private System.Windows.Forms.ToolStripMenuItem runToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem removeToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
|
||||
private System.Windows.Forms.ToolStripMenuItem addToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem editToolStripMenuItem;
|
||||
private System.Windows.Forms.Button editButton;
|
||||
private System.Windows.Forms.Button runButton;
|
||||
}
|
||||
}
|
||||
141
CustomAppsForm.cs
Normal file
141
CustomAppsForm.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Forms;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MeshCentralRouter
|
||||
{
|
||||
public partial class CustomAppsForm : Form
|
||||
{
|
||||
List<string[]> apps;
|
||||
|
||||
public CustomAppsForm(List<string[]> apps)
|
||||
{
|
||||
this.apps = apps;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void CustomAppsForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
if (apps != null) {
|
||||
foreach (string[] app in apps) {
|
||||
string[] x = new string[5];
|
||||
x[0] = app[0];
|
||||
x[1] = app[1];
|
||||
x[2] = "\"" + app[2] + "\" " + app[3];
|
||||
x[3] = app[2];
|
||||
x[4] = app[3];
|
||||
mainListView.Items.Add(new ListViewItem(x));
|
||||
}
|
||||
}
|
||||
UpdateInfo();
|
||||
}
|
||||
|
||||
public List<string[]> getApplications()
|
||||
{
|
||||
List<string[]> r = new List<string[]>();
|
||||
foreach (ListViewItem l in mainListView.Items)
|
||||
{
|
||||
string[] x = new string[4];
|
||||
x[0] = l.SubItems[0].Text;
|
||||
x[1] = l.SubItems[1].Text.ToLower();
|
||||
x[2] = l.SubItems[3].Text;
|
||||
x[3] = l.SubItems[4].Text;
|
||||
r.Add(x);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
private void addButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
CustomAppsAddForm f = new CustomAppsAddForm();
|
||||
if (f.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
// Remove any matching protocol
|
||||
List<ListViewItem> list = new List<ListViewItem>();
|
||||
foreach (ListViewItem l in mainListView.Items) { if (l.SubItems[1].Text.ToLower() == f.appProtocol.ToLower()) { list.Add(l); } }
|
||||
foreach (ListViewItem l in list) { mainListView.Items.Remove(l); }
|
||||
|
||||
// Add the new protocol
|
||||
string[] x = new string[5];
|
||||
x[0] = f.appName;
|
||||
x[1] = f.appProtocol.ToLower();
|
||||
x[2] = "\"" + f.appCommand + "\" " + f.appArgs;
|
||||
x[3] = f.appCommand;
|
||||
x[4] = f.appArgs;
|
||||
mainListView.Items.Add(new ListViewItem(x));
|
||||
}
|
||||
}
|
||||
|
||||
private void okButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.OK;
|
||||
}
|
||||
|
||||
private void cancelButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.Cancel;
|
||||
}
|
||||
|
||||
private void mainListView_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
UpdateInfo();
|
||||
}
|
||||
|
||||
private void UpdateInfo()
|
||||
{
|
||||
removeButton.Enabled = (mainListView.SelectedItems.Count > 0);
|
||||
runButton.Enabled = editButton.Enabled = (mainListView.SelectedItems.Count == 1);
|
||||
}
|
||||
|
||||
private void removeButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (mainListView.SelectedItems.Count == 0) return;
|
||||
List<ListViewItem> list = new List<ListViewItem>();
|
||||
foreach (ListViewItem l in mainListView.SelectedItems) { list.Add(l); }
|
||||
foreach (ListViewItem l in list) { mainListView.Items.Remove(l); }
|
||||
}
|
||||
|
||||
private void appContextMenuStrip_Opening(object sender, CancelEventArgs e)
|
||||
{
|
||||
runToolStripMenuItem.Visible = (mainListView.SelectedItems.Count == 1);
|
||||
removeToolStripMenuItem.Visible = toolStripMenuItem1.Visible = (mainListView.SelectedItems.Count > 0);
|
||||
}
|
||||
|
||||
private void runToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (mainListView.SelectedItems.Count != 1) return;
|
||||
ListViewItem i = mainListView.SelectedItems[0];
|
||||
CustomAppsRunForm f = new CustomAppsRunForm(i.SubItems[3].Text, i.SubItems[4].Text);
|
||||
if (f.ShowDialog(this) == DialogResult.OK) { Process.Start(i.SubItems[3].Text, f.getFinalArgs()); }
|
||||
}
|
||||
|
||||
private void editToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (mainListView.SelectedItems.Count != 1) return;
|
||||
ListViewItem i = mainListView.SelectedItems[0];
|
||||
CustomAppsAddForm f = new CustomAppsAddForm();
|
||||
f.appName = i.SubItems[0].Text;
|
||||
f.appProtocol = i.SubItems[1].Text;
|
||||
f.appCommand = i.SubItems[3].Text;
|
||||
f.appArgs = i.SubItems[4].Text;
|
||||
if (f.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
// Remove any matching protocol
|
||||
List<ListViewItem> list = new List<ListViewItem>();
|
||||
foreach (ListViewItem l in mainListView.Items) { if (l.SubItems[1].Text.ToLower() == f.appProtocol.ToLower()) { list.Add(l); } }
|
||||
foreach (ListViewItem l in list) { mainListView.Items.Remove(l); }
|
||||
|
||||
// Add the new protocol
|
||||
string[] x = new string[5];
|
||||
x[0] = f.appName;
|
||||
x[1] = f.appProtocol.ToLower();
|
||||
x[2] = "\"" + f.appCommand + "\" " + f.appArgs;
|
||||
x[3] = f.appCommand;
|
||||
x[4] = f.appArgs;
|
||||
mainListView.Items.Add(new ListViewItem(x));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1818
CustomAppsForm.resx
Normal file
1818
CustomAppsForm.resx
Normal file
File diff suppressed because it is too large
Load Diff
243
CustomAppsRunForm.Designer.cs
generated
Normal file
243
CustomAppsRunForm.Designer.cs
generated
Normal file
@@ -0,0 +1,243 @@
|
||||
namespace MeshCentralRouter
|
||||
{
|
||||
partial class CustomAppsRunForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CustomAppsRunForm));
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.portTextBox = new System.Windows.Forms.TextBox();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.addressTextBox = new System.Windows.Forms.TextBox();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.commandTextBox = new System.Windows.Forms.TextBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.okButton = new System.Windows.Forms.Button();
|
||||
this.cancelButton = new System.Windows.Forms.Button();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.argsTextBox = new System.Windows.Forms.TextBox();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
this.nameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.label6 = new System.Windows.Forms.Label();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.groupBox1.Controls.Add(this.nameTextBox);
|
||||
this.groupBox1.Controls.Add(this.label6);
|
||||
this.groupBox1.Controls.Add(this.argsTextBox);
|
||||
this.groupBox1.Controls.Add(this.label5);
|
||||
this.groupBox1.Controls.Add(this.portTextBox);
|
||||
this.groupBox1.Controls.Add(this.label4);
|
||||
this.groupBox1.Controls.Add(this.addressTextBox);
|
||||
this.groupBox1.Controls.Add(this.label3);
|
||||
this.groupBox1.Controls.Add(this.commandTextBox);
|
||||
this.groupBox1.Controls.Add(this.label2);
|
||||
this.groupBox1.Location = new System.Drawing.Point(12, 49);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(382, 155);
|
||||
this.groupBox1.TabIndex = 0;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "Application Command";
|
||||
//
|
||||
// portTextBox
|
||||
//
|
||||
this.portTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.portTextBox.Location = new System.Drawing.Point(116, 97);
|
||||
this.portTextBox.Name = "portTextBox";
|
||||
this.portTextBox.Size = new System.Drawing.Size(260, 20);
|
||||
this.portTextBox.TabIndex = 13;
|
||||
this.portTextBox.Text = "1234";
|
||||
this.portTextBox.TextChanged += new System.EventHandler(this.portTextBox_TextChanged);
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(6, 100);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(44, 13);
|
||||
this.label4.TabIndex = 12;
|
||||
this.label4.Text = "Port %P";
|
||||
//
|
||||
// addressTextBox
|
||||
//
|
||||
this.addressTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.addressTextBox.Location = new System.Drawing.Point(116, 71);
|
||||
this.addressTextBox.Name = "addressTextBox";
|
||||
this.addressTextBox.Size = new System.Drawing.Size(260, 20);
|
||||
this.addressTextBox.TabIndex = 11;
|
||||
this.addressTextBox.Text = "127.0.0.1";
|
||||
this.addressTextBox.TextChanged += new System.EventHandler(this.addressTextBox_TextChanged);
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(6, 74);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(62, 13);
|
||||
this.label3.TabIndex = 10;
|
||||
this.label3.Text = "Address %L";
|
||||
//
|
||||
// commandTextBox
|
||||
//
|
||||
this.commandTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.commandTextBox.Location = new System.Drawing.Point(116, 19);
|
||||
this.commandTextBox.Name = "commandTextBox";
|
||||
this.commandTextBox.ReadOnly = true;
|
||||
this.commandTextBox.Size = new System.Drawing.Size(260, 20);
|
||||
this.commandTextBox.TabIndex = 9;
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(6, 22);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(54, 13);
|
||||
this.label2.TabIndex = 8;
|
||||
this.label2.Text = "Command";
|
||||
//
|
||||
// okButton
|
||||
//
|
||||
this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.okButton.Location = new System.Drawing.Point(238, 210);
|
||||
this.okButton.Name = "okButton";
|
||||
this.okButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.okButton.TabIndex = 3;
|
||||
this.okButton.Text = "OK";
|
||||
this.okButton.UseVisualStyleBackColor = true;
|
||||
this.okButton.Click += new System.EventHandler(this.okButton_Click);
|
||||
//
|
||||
// cancelButton
|
||||
//
|
||||
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.cancelButton.Location = new System.Drawing.Point(319, 210);
|
||||
this.cancelButton.Name = "cancelButton";
|
||||
this.cancelButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.cancelButton.TabIndex = 2;
|
||||
this.cancelButton.Text = "Cancel";
|
||||
this.cancelButton.UseVisualStyleBackColor = true;
|
||||
this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.label1.Location = new System.Drawing.Point(12, 11);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(382, 35);
|
||||
this.label1.TabIndex = 4;
|
||||
this.label1.Text = "Test that the application runs correctly by specifying and address, port and name" +
|
||||
". Then click ok to run the application.";
|
||||
//
|
||||
// argsTextBox
|
||||
//
|
||||
this.argsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.argsTextBox.Location = new System.Drawing.Point(116, 45);
|
||||
this.argsTextBox.Name = "argsTextBox";
|
||||
this.argsTextBox.ReadOnly = true;
|
||||
this.argsTextBox.Size = new System.Drawing.Size(260, 20);
|
||||
this.argsTextBox.TabIndex = 15;
|
||||
//
|
||||
// label5
|
||||
//
|
||||
this.label5.AutoSize = true;
|
||||
this.label5.Location = new System.Drawing.Point(6, 48);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(57, 13);
|
||||
this.label5.TabIndex = 14;
|
||||
this.label5.Text = "Arguments";
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.nameTextBox.Location = new System.Drawing.Point(116, 123);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(260, 20);
|
||||
this.nameTextBox.TabIndex = 17;
|
||||
this.nameTextBox.Text = "MyComputer";
|
||||
//
|
||||
// label6
|
||||
//
|
||||
this.label6.AutoSize = true;
|
||||
this.label6.Location = new System.Drawing.Point(6, 126);
|
||||
this.label6.Name = "label6";
|
||||
this.label6.Size = new System.Drawing.Size(54, 13);
|
||||
this.label6.TabIndex = 16;
|
||||
this.label6.Text = "Name %N";
|
||||
//
|
||||
// CustomAppsRunForm
|
||||
//
|
||||
this.AcceptButton = this.okButton;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.cancelButton;
|
||||
this.ClientSize = new System.Drawing.Size(406, 245);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.okButton);
|
||||
this.Controls.Add(this.cancelButton);
|
||||
this.Controls.Add(this.groupBox1);
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "CustomAppsRunForm";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Test Application";
|
||||
this.Load += new System.EventHandler(this.CustomAppsRunForm_Load);
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.groupBox1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
private System.Windows.Forms.Button okButton;
|
||||
private System.Windows.Forms.Button cancelButton;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.TextBox portTextBox;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.TextBox addressTextBox;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.TextBox commandTextBox;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.TextBox argsTextBox;
|
||||
private System.Windows.Forms.Label label5;
|
||||
private System.Windows.Forms.TextBox nameTextBox;
|
||||
private System.Windows.Forms.Label label6;
|
||||
}
|
||||
}
|
||||
61
CustomAppsRunForm.cs
Normal file
61
CustomAppsRunForm.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MeshCentralRouter
|
||||
{
|
||||
public partial class CustomAppsRunForm : Form
|
||||
{
|
||||
private string command = null;
|
||||
private string args = null;
|
||||
|
||||
public CustomAppsRunForm(string command, string args)
|
||||
{
|
||||
this.command = command;
|
||||
this.args = args;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public string getFinalArgs()
|
||||
{
|
||||
return args.Replace("%L", addressTextBox.Text).Replace("%P", portTextBox.Text).Replace("%N", nameTextBox.Text);
|
||||
}
|
||||
|
||||
public void UpdateInfo()
|
||||
{
|
||||
commandTextBox.Text = command;
|
||||
argsTextBox.Text = getFinalArgs();
|
||||
}
|
||||
|
||||
private void addressTextBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
UpdateInfo();
|
||||
}
|
||||
|
||||
private void portTextBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
UpdateInfo();
|
||||
}
|
||||
|
||||
private void CustomAppsRunForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
UpdateInfo();
|
||||
}
|
||||
|
||||
private void okButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.OK;
|
||||
}
|
||||
|
||||
private void cancelButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.Cancel;
|
||||
}
|
||||
}
|
||||
}
|
||||
1815
CustomAppsRunForm.resx
Normal file
1815
CustomAppsRunForm.resx
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
3730
FileViewer.cs
3730
FileViewer.cs
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
2
KVMControl.Designer.cs
generated
2
KVMControl.Designer.cs
generated
@@ -37,6 +37,7 @@
|
||||
this.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.Name = "KVMControl";
|
||||
this.Size = new System.Drawing.Size(585, 364);
|
||||
this.Load += new System.EventHandler(this.KVMControl_Load);
|
||||
this.Paint += new System.Windows.Forms.PaintEventHandler(this.KVMControl_Paint);
|
||||
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.KVMControl_KeyDown);
|
||||
this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.KVMControl_KeyPress);
|
||||
@@ -45,7 +46,6 @@
|
||||
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.KVMControl_MouseMove);
|
||||
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.KVMControl_MouseUp);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
299
KVMControl.cs
299
KVMControl.cs
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -22,13 +22,15 @@ using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace MeshCentralRouter
|
||||
{
|
||||
public partial class KVMControl : UserControl
|
||||
{
|
||||
private bool remotepause = true;
|
||||
private Bitmap desktop = null;
|
||||
public Bitmap desktop = null;
|
||||
private Graphics desktopGraphics = null;
|
||||
public uint screenWidth = 0;
|
||||
public uint screenHeight = 0;
|
||||
@@ -40,6 +42,7 @@ namespace MeshCentralRouter
|
||||
private bool swamMouseButtons = false;
|
||||
private bool remoteKeyboardMap = false;
|
||||
private bool autoSendClipboard = false;
|
||||
public bool AutoReconnect = false;
|
||||
private double scalefactor = 1;
|
||||
public List<ushort> displays = new List<ushort>();
|
||||
public ushort currentDisp = 0;
|
||||
@@ -49,15 +52,70 @@ namespace MeshCentralRouter
|
||||
public double DpiX = 96;
|
||||
public double DpiY = 96;
|
||||
public KVMViewer parent = null;
|
||||
public KVMViewerExtra parentEx = null;
|
||||
private readonly KVMControlHook ControlHook;
|
||||
private readonly KVMControlHook.KVMCallback KeyboardCallback;
|
||||
private bool isHookWanted;
|
||||
private bool isHookPriority;
|
||||
private bool keyboardIsAttached;
|
||||
private long killNextKeyPress = 0;
|
||||
private bool controlLoaded = false;
|
||||
public Rectangle[] displayInfo = null;
|
||||
public Rectangle displayCrop = Rectangle.Empty;
|
||||
public Point displayOrigin = Point.Empty;
|
||||
|
||||
|
||||
private enum KvmCommands
|
||||
//System level functions to be used for hook and unhook keyboard input
|
||||
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
private static extern IntPtr SetWindowsHookEx(int id, LowLevelKeyboardProc callback, IntPtr hMod, uint dwThreadId);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
private static extern bool UnhookWindowsHookEx(IntPtr hook);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
private static extern IntPtr CallNextHookEx(IntPtr hook, int nCode, IntPtr wp, IntPtr lp);
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
private static extern IntPtr GetModuleHandle(string name);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||
private static extern short GetAsyncKeyState(Keys key);
|
||||
[DllImport("user32.dll")]
|
||||
static extern IntPtr GetForegroundWindow();
|
||||
|
||||
|
||||
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)] public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
|
||||
[DllImport("gdi32.dll", ExactSpelling = true)] public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
|
||||
[DllImport("gdi32.dll", ExactSpelling = true)] public static extern IntPtr DeleteObject(IntPtr hObject);
|
||||
[DllImport("gdi32.dll")] private static extern bool BitBlt(IntPtr hdcDest, Int32 nXDest, Int32 nYDest, Int32 nWidth, Int32 nHeight, IntPtr hdcSrc, Int32 nXSrc, Int32 nYSrc, TernaryRasterOperations dwRop);
|
||||
[DllImport("gdi32.dll")] private static extern bool StretchBlt(IntPtr hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, TernaryRasterOperations dwRop);
|
||||
[DllImport("gdi32.dll")] static extern bool SetStretchBltMode(IntPtr hdc, StretchMode iStretchMode);
|
||||
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)] private static extern bool DeleteDC(IntPtr hdc);
|
||||
public enum StretchMode
|
||||
{
|
||||
STRETCH_ANDSCANS = 1,
|
||||
STRETCH_ORSCANS = 2,
|
||||
STRETCH_DELETESCANS = 3,
|
||||
STRETCH_HALFTONE = 4,
|
||||
}
|
||||
|
||||
public enum TernaryRasterOperations
|
||||
{
|
||||
SRCCOPY = 0x00CC0020, /* dest = source*/
|
||||
SRCPAINT = 0x00EE0086, /* dest = source OR dest*/
|
||||
SRCAND = 0x008800C6, /* dest = source AND dest*/
|
||||
SRCINVERT = 0x00660046, /* dest = source XOR dest*/
|
||||
SRCERASE = 0x00440328, /* dest = source AND (NOT dest )*/
|
||||
NOTSRCCOPY = 0x00330008, /* dest = (NOT source)*/
|
||||
NOTSRCERASE = 0x001100A6, /* dest = (NOT src) AND (NOT dest) */
|
||||
MERGECOPY = 0x00C000CA, /* dest = (source AND pattern)*/
|
||||
MERGEPAINT = 0x00BB0226, /* dest = (NOT source) OR dest*/
|
||||
PATCOPY = 0x00F00021, /* dest = pattern*/
|
||||
PATPAINT = 0x00FB0A09, /* dest = DPSnoo*/
|
||||
PATINVERT = 0x005A0049, /* dest = pattern XOR dest*/
|
||||
DSTINVERT = 0x00550009, /* dest = (NOT dest)*/
|
||||
BLACKNESS = 0x00000042, /* dest = BLACK*/
|
||||
WHITENESS = 0x00FF0062, /* dest = WHITE*/
|
||||
};
|
||||
|
||||
private enum KvmCommands
|
||||
{
|
||||
Nop = 0,
|
||||
Key = 1,
|
||||
@@ -79,6 +137,7 @@ namespace MeshCentralRouter
|
||||
Jumbo = 27,
|
||||
Disconnect = 59,
|
||||
Alert = 65,
|
||||
DisplayInfo = 82,
|
||||
KeyUnicode = 85,
|
||||
MouseCursor = 88
|
||||
}
|
||||
@@ -101,6 +160,9 @@ namespace MeshCentralRouter
|
||||
[Description("Fires when it receives the display list.")]
|
||||
public event EventHandler DisplaysReceived;
|
||||
|
||||
public delegate void ScreenAreaUpdatedHandler(Bitmap desktop, Rectangle r);
|
||||
public event ScreenAreaUpdatedHandler ScreenAreaUpdated;
|
||||
|
||||
public enum ConnectState
|
||||
{
|
||||
Disconnected,
|
||||
@@ -118,8 +180,14 @@ namespace MeshCentralRouter
|
||||
public double ScaleFactor { get { return scalefactor; } set { scalefactor = value; } }
|
||||
|
||||
public void SetCompressionParams(int level, int scaling, int framerate) { compressionlevel = level; scalinglevel = scaling; frameRate = framerate; SendCompressionLevel(); }
|
||||
public int DesktopWidth { get { return (int)screenWidth; } }
|
||||
public int DesktopHeight { get { return (int)screenHeight; } }
|
||||
public int DesktopWidth
|
||||
{
|
||||
get { if (displayCrop == Rectangle.Empty) { return (int)screenWidth; } else { return displayCrop.Width; } }
|
||||
}
|
||||
public int DesktopHeight
|
||||
{
|
||||
get { if (displayCrop == Rectangle.Empty) { return (int)screenHeight; } else { return displayCrop.Height; } }
|
||||
}
|
||||
|
||||
// Debug
|
||||
public int bytesent = 0;
|
||||
@@ -218,7 +286,7 @@ namespace MeshCentralRouter
|
||||
ushort tile_y = (ushort)((buffer[off + 6] << 8) + buffer[off + 7]);
|
||||
try { newtile = Image.FromStream(new System.IO.MemoryStream(buffer, off + 8, blen - 8)); } catch (Exception) { return blen; }
|
||||
Rectangle r = new Rectangle((int)tile_x, (int)tile_y, newtile.Width, newtile.Height);
|
||||
Rectangle r3 = new Rectangle((int)((double)tile_x / (double)scalefactor) - 2, (int)((double)tile_y / (double)scalefactor) - 2, (int)((double)newtile.Width / (double)scalefactor) + 4, (int)((double)newtile.Height / (double)scalefactor) + 4);
|
||||
Rectangle r3 = new Rectangle((int)Math.Round((double)tile_x / (double)scalefactor) - 2, (int)Math.Round((double)tile_y / (double)scalefactor) - 2, (int)Math.Round((double)newtile.Width / (double)scalefactor) + 4, (int)Math.Round((double)newtile.Height / (double)scalefactor) + 4);
|
||||
tilecount++;
|
||||
|
||||
// Winform mode
|
||||
@@ -226,14 +294,61 @@ namespace MeshCentralRouter
|
||||
{
|
||||
lock (desktop)
|
||||
{
|
||||
desktopGraphics.DrawImage(newtile, new Rectangle((int)tile_x, (int)tile_y, newtile.Width, newtile.Height), new Rectangle(0, 0, newtile.Width, newtile.Height), GraphicsUnit.Pixel);
|
||||
if (debugmode)
|
||||
Graphics MemGraphics = Graphics.FromImage(newtile);
|
||||
|
||||
IntPtr hBitmap = ((Bitmap)newtile).GetHbitmap();
|
||||
IntPtr memdc = MemGraphics.GetHdc();
|
||||
IntPtr pOrig = SelectObject(memdc, hBitmap);
|
||||
IntPtr dcDst = desktopGraphics.GetHdc();
|
||||
|
||||
|
||||
bool bok = BitBlt(dcDst, (int)tile_x, (int)tile_y, (int)newtile.Width, (int)newtile.Height, memdc, (int)0, (int)0, TernaryRasterOperations.SRCCOPY);
|
||||
|
||||
IntPtr pNew = SelectObject(memdc, pOrig); // == hBitmap
|
||||
DeleteObject(pNew);
|
||||
desktopGraphics.ReleaseHdc(dcDst);
|
||||
MemGraphics.ReleaseHdc(memdc);
|
||||
if(debugmode)
|
||||
{
|
||||
desktopGraphics.DrawRectangle(RedPen, new Rectangle((int)tile_x, (int)tile_y, newtile.Width - 1, newtile.Height - 1));
|
||||
desktopGraphics.DrawString(string.Format("{0} / {1}kb", tilecount, blen / 2014), DebugFont, RedPen.Brush, new Point((int)tile_x, (int)tile_y));
|
||||
}
|
||||
}
|
||||
if (scalefactor == 1) Invalidate(r, false); else Invalidate(r3, false);
|
||||
|
||||
// Update extra displays if needed
|
||||
Rectangle r = new Rectangle((int)tile_x, (int)tile_y, newtile.Width, newtile.Height);
|
||||
Rectangle rx = new Rectangle(r.X + displayOrigin.X, r.Y + displayOrigin.Y, r.Width, r.Height);
|
||||
//Console.WriteLine(rx.ToString());
|
||||
if (ScreenAreaUpdated != null) ScreenAreaUpdated(desktop, rx);
|
||||
|
||||
if (displayCrop == Rectangle.Empty)
|
||||
{
|
||||
if (scalefactor == 1)
|
||||
{
|
||||
Invalidate(r, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Rectangle r3 = new Rectangle((int)((double)tile_x / (double)scalefactor) - 2, (int)((double)tile_y / (double)scalefactor) - 2, (int)((double)newtile.Width / (double)scalefactor) + 4, (int)((double)newtile.Height / (double)scalefactor) + 4);
|
||||
Invalidate(r3, false);
|
||||
}
|
||||
}
|
||||
else if (displayCrop.IntersectsWith(rx) == true)
|
||||
{
|
||||
Rectangle r2 = new Rectangle(rx.X, rx.Y, rx.Width, rx.Height);
|
||||
r2.Intersect(displayCrop);
|
||||
|
||||
if (scalefactor == 1)
|
||||
{
|
||||
Rectangle r3 = new Rectangle(r2.X - displayCrop.X, r2.Y - displayCrop.Y, r2.Width, r2.Height);
|
||||
Invalidate(r, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Rectangle r3 = new Rectangle((int)((double)(r2.X - displayCrop.X) / (double)scalefactor) - 2, (int)((double)(r2.Y - displayCrop.Y) / (double)scalefactor) - 2, (int)((double)r2.Width / (double)scalefactor) + 4, (int)((double)r2.Height / (double)scalefactor) + 4);
|
||||
Invalidate(r3, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blen + jumboHeaderSize;
|
||||
@@ -289,6 +404,31 @@ namespace MeshCentralRouter
|
||||
ChangeMouseCursor(buffer[off + 4]);
|
||||
break;
|
||||
}
|
||||
case KvmCommands.DisplayInfo:
|
||||
{
|
||||
if ((blen < 4) || (((blen - 4) % 10) != 0)) break;
|
||||
int screenCount = ((blen - 4) / 10);
|
||||
int ptr = off + 4;
|
||||
Rectangle[] xDisplayInfo = new Rectangle[screenCount];
|
||||
|
||||
for (var i = 0; i < screenCount; i++)
|
||||
{
|
||||
int id = ((buffer[ptr + 0] << 8) + buffer[ptr + 1]);
|
||||
int x = ((buffer[ptr + 2] << 8) + buffer[ptr + 3]);
|
||||
int y = ((buffer[ptr + 4] << 8) + buffer[ptr + 5]);
|
||||
int w = ((buffer[ptr + 6] << 8) + buffer[ptr + 7]);
|
||||
int h = ((buffer[ptr + 8] << 8) + buffer[ptr + 9]);
|
||||
if (x > 32766) { x -= 65536; }
|
||||
if (y > 32766) { y -= 65536; }
|
||||
Rectangle r = new Rectangle(x, y, w, h);
|
||||
xDisplayInfo[id - 1] = r;
|
||||
ptr += 10;
|
||||
}
|
||||
|
||||
// Set display information
|
||||
displayInfo = xDisplayInfo;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
// MessageBox.Show("Should never happen!");
|
||||
@@ -333,6 +473,11 @@ namespace MeshCentralRouter
|
||||
Invalidate(region);
|
||||
}
|
||||
|
||||
public void Repaint(Rectangle rect)
|
||||
{
|
||||
Invalidate(rect);
|
||||
}
|
||||
|
||||
protected override void OnPaintBackground(PaintEventArgs e)
|
||||
{
|
||||
// Do not paint background.
|
||||
@@ -355,14 +500,28 @@ namespace MeshCentralRouter
|
||||
{
|
||||
lock (desktop)
|
||||
{
|
||||
if (scalefactor == 1)
|
||||
if (displayCrop == Rectangle.Empty) // No cropping
|
||||
{
|
||||
g.DrawImage(desktop, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel);
|
||||
if (scalefactor == 1)
|
||||
{
|
||||
g.DrawImage(desktop, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel);
|
||||
}
|
||||
else
|
||||
{
|
||||
g.DrawImage((Image)desktop, e.ClipRectangle, (int)((double)e.ClipRectangle.Left * (double)scalefactor), (int)((double)e.ClipRectangle.Top * (double)scalefactor), (int)((double)e.ClipRectangle.Width * (double)scalefactor), (int)((double)e.ClipRectangle.Height * (double)scalefactor), GraphicsUnit.Pixel);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//g.DrawImage((Image)desktop, new Rectangle(0, 0, Width, Height), 0, 0, screenWidth, screenHeight, GraphicsUnit.Pixel);
|
||||
g.DrawImage((Image)desktop, e.ClipRectangle, (int)((double)e.ClipRectangle.Left * (double)scalefactor), (int)((double)e.ClipRectangle.Top * (double)scalefactor), (int)((double)e.ClipRectangle.Width * (double)scalefactor), (int)((double)e.ClipRectangle.Height * (double)scalefactor), GraphicsUnit.Pixel);
|
||||
if (scalefactor == 1) // Cropping in effect, this is when we show different displays in different windows
|
||||
{
|
||||
g.DrawImage(desktop, e.ClipRectangle, new Rectangle(e.ClipRectangle.X - displayOrigin.X + displayCrop.X, e.ClipRectangle.Y - displayOrigin.Y + displayCrop.Y, e.ClipRectangle.Width, e.ClipRectangle.Height), GraphicsUnit.Pixel);
|
||||
}
|
||||
else
|
||||
{
|
||||
Rectangle srcRect = new Rectangle((int)((double)(e.ClipRectangle.Left) * (double)scalefactor) - displayOrigin.X + displayCrop.X, (int)((double)(e.ClipRectangle.Top) * (double)scalefactor) - displayOrigin.Y + displayCrop.Y, (int)((double)e.ClipRectangle.Width * (double)scalefactor), (int)((double)e.ClipRectangle.Height * (double)scalefactor));
|
||||
g.DrawImage((Image)desktop, e.ClipRectangle, srcRect, GraphicsUnit.Pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -422,7 +581,7 @@ namespace MeshCentralRouter
|
||||
|
||||
if (remoteKeyboardMap == true) { SendKey((byte)e.KeyCode, action); return; } // Use old key system that uses the remote keyboard mapping.
|
||||
string keycode = e.KeyCode.ToString();
|
||||
if ((action == 0) && (e.Control == false) && (e.Alt == false) && (((e.KeyValue >= 48) && (e.KeyValue <= 57)) || (keycode.Length == 1) || (keycode.StartsWith("Oem") == true))) return;
|
||||
if ((action == 0) && (e.Control == false) && (e.Alt == false) && (((e.KeyValue >= 48) && (e.KeyValue <= 57))|| ((e.KeyValue >= 96) && (e.KeyValue <= 105)) || (keycode.Length == 1) || (keycode.StartsWith("Oem") == true))) return;
|
||||
if ((e.Control == true) || (e.Alt == true)) { killNextKeyPress = DateTime.Now.Ticks; }
|
||||
SendKey((byte)e.KeyCode, action);
|
||||
e.Handled = true;
|
||||
@@ -479,8 +638,16 @@ namespace MeshCentralRouter
|
||||
}
|
||||
}
|
||||
|
||||
LastX = (short)((double)e.X * (double)scalefactor);
|
||||
LastY = (short)((double)e.Y * (double)scalefactor);
|
||||
if (displayCrop == Rectangle.Empty)
|
||||
{
|
||||
LastX = (short)((double)e.X * (double)scalefactor);
|
||||
LastY = (short)((double)e.Y * (double)scalefactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
LastX = (short)((int)((double)e.X * (double)scalefactor) - displayOrigin.X + displayCrop.X);
|
||||
LastY = (short)((int)((double)e.Y * (double)scalefactor) - displayOrigin.Y + displayCrop.Y);
|
||||
}
|
||||
|
||||
BinaryWriter bw = GetBinaryWriter();
|
||||
bw.Write(IPAddress.HostToNetworkOrder((short)KvmCommands.Mouse));
|
||||
@@ -563,9 +730,16 @@ namespace MeshCentralRouter
|
||||
//if (state == ConnectState.Disconnected) return;
|
||||
try
|
||||
{
|
||||
parent.bytesOut += buffer.Length;
|
||||
parent.bytesOutCompressed += parent.wc.SendBinary(buffer, 0, buffer.Length);
|
||||
bytesent += buffer.Length;
|
||||
if (parent != null)
|
||||
{
|
||||
parent.bytesOut += buffer.Length;
|
||||
parent.bytesOutCompressed += parent.wc.SendBinary(buffer, 0, buffer.Length);
|
||||
bytesent += buffer.Length;
|
||||
}
|
||||
else if (parentEx != null)
|
||||
{
|
||||
parentEx.mainKvmControl.Send(buffer);
|
||||
}
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
@@ -575,9 +749,16 @@ namespace MeshCentralRouter
|
||||
//if (state == ConnectState.Disconnected) return;
|
||||
try
|
||||
{
|
||||
parent.bytesOut += str.Length;
|
||||
parent.bytesOutCompressed += parent.wc.SendString(str);
|
||||
bytesent += str.Length;
|
||||
if (parent != null)
|
||||
{
|
||||
parent.bytesOut += str.Length;
|
||||
parent.bytesOutCompressed += parent.wc.SendString(str);
|
||||
bytesent += str.Length;
|
||||
}
|
||||
else if (parentEx != null)
|
||||
{
|
||||
parentEx.mainKvmControl.Send(str);
|
||||
}
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
@@ -595,6 +776,10 @@ namespace MeshCentralRouter
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
else if (parentEx != null)
|
||||
{
|
||||
parentEx.mainKvmControl.Send(bw);
|
||||
}
|
||||
RecycleBinaryWriter(bw);
|
||||
}
|
||||
|
||||
@@ -738,5 +923,75 @@ namespace MeshCentralRouter
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Structure contain information about low-level keyboard input event
|
||||
private struct KBDLLHOOKSTRUCT
|
||||
{
|
||||
public Keys key;
|
||||
public int scanCode;
|
||||
public int flags;
|
||||
public int time;
|
||||
public IntPtr extra;
|
||||
}
|
||||
|
||||
public void cropDisplay(Point o, Rectangle r)
|
||||
{
|
||||
if (IsDisposed || Disposing) return;
|
||||
displayCrop = r;
|
||||
displayOrigin = o;
|
||||
if (controlLoaded)
|
||||
{
|
||||
Invoke(new SetSizeHandler(SetSize));
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private void KVMControl_Load(object sender, EventArgs e)
|
||||
{
|
||||
controlLoaded = true;
|
||||
}
|
||||
|
||||
//Declaring Global objects
|
||||
private IntPtr ptrHook;
|
||||
private LowLevelKeyboardProc objKeyboardProcess;
|
||||
|
||||
private IntPtr captureKey(int nCode, IntPtr wp, IntPtr lp)
|
||||
{
|
||||
bool bIsForegroundWindow = false;
|
||||
try { bIsForegroundWindow = GetForegroundWindow() == this.ParentForm.Handle; } catch { }
|
||||
if(nCode >= 0 && bIsForegroundWindow)
|
||||
{
|
||||
KBDLLHOOKSTRUCT objKeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT));
|
||||
|
||||
// Disabling Windows keys
|
||||
|
||||
if(objKeyInfo.key == Keys.RWin || objKeyInfo.key == Keys.LWin)
|
||||
{
|
||||
bool bKeyDown = wp == (IntPtr)0x0100/*WM_KEYDOWN*/;
|
||||
SendKey(new KeyEventArgs((Keys)objKeyInfo.key), (byte)(bKeyDown ? 0 : 1));
|
||||
// SendKey(new KeyEventArgs((Keys)objKeyInfo.key), 0);
|
||||
return (IntPtr)1; // if 0 is returned then All the above keys will be enabled
|
||||
// return (IntPtr)0; // if 0 is returned then All the above keys will be enabled
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
return CallNextHookEx(ptrHook, nCode, wp, lp);
|
||||
}
|
||||
|
||||
bool HasAltModifier(int flags)
|
||||
{
|
||||
return (flags & 0x20) == 0x20;
|
||||
}
|
||||
|
||||
private void KVMControl_Load(object sender, EventArgs e)
|
||||
{
|
||||
ProcessModule objCurrentModule = Process.GetCurrentProcess().MainModule;
|
||||
objKeyboardProcess = new LowLevelKeyboardProc(captureKey);
|
||||
ptrHook = SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0);
|
||||
}
|
||||
|
||||
/* Code to Disable WinKey, Alt+Tab, Ctrl+Esc Ends Here */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
4
KVMResizeControl.Designer.cs
generated
4
KVMResizeControl.Designer.cs
generated
@@ -89,14 +89,18 @@
|
||||
//
|
||||
// kvmControl
|
||||
//
|
||||
this.kvmControl.AutoSendClipboard = false;
|
||||
this.kvmControl.BackColor = System.Drawing.Color.LightCoral;
|
||||
this.kvmControl.CompressionLevel = 60;
|
||||
this.kvmControl.FrameRate = 100;
|
||||
this.kvmControl.Location = new System.Drawing.Point(33, 31);
|
||||
this.kvmControl.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.kvmControl.Name = "kvmControl";
|
||||
this.kvmControl.RemoteKeyboardMap = false;
|
||||
this.kvmControl.ScaleFactor = 1D;
|
||||
this.kvmControl.ScalingLevel = 1024;
|
||||
this.kvmControl.Size = new System.Drawing.Size(450, 314);
|
||||
this.kvmControl.SwamMouseButtons = false;
|
||||
this.kvmControl.TabIndex = 14;
|
||||
this.kvmControl.DesktopSizeChanged += new System.EventHandler(this.kvmControl_DesktopSizeChanged);
|
||||
this.kvmControl.Resize += new System.EventHandler(this.kvmControl_Resize);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -47,6 +47,7 @@ namespace MeshCentralRouter
|
||||
CenterKvmControl(false);
|
||||
}
|
||||
|
||||
/*
|
||||
void KVM_StateChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (InvokeRequired) { Invoke(new EventHandler(KVM_StateChanged), sender, e); return; }
|
||||
@@ -55,6 +56,7 @@ namespace MeshCentralRouter
|
||||
//kvmControl.Visible = (kvmControl.State == KVMControl.ConnectState.Connected);
|
||||
if (StateChanged != null) StateChanged(this, e);
|
||||
}
|
||||
*/
|
||||
|
||||
void KVM_DisplaysReceived(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
19
KVMSettingsForm.Designer.cs
generated
19
KVMSettingsForm.Designer.cs
generated
@@ -32,6 +32,7 @@
|
||||
this.cancelButton = new System.Windows.Forms.Button();
|
||||
this.okButton = new System.Windows.Forms.Button();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.autoSendClipboardCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.remoteKeyboardMapCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.swapMouseButtonsCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.frameRateComboBox = new System.Windows.Forms.ComboBox();
|
||||
@@ -42,7 +43,7 @@
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.pictureBox1 = new System.Windows.Forms.PictureBox();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.autoSendClipboardCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.autoReconnectCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.groupBox1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
@@ -65,6 +66,7 @@
|
||||
// groupBox1
|
||||
//
|
||||
resources.ApplyResources(this.groupBox1, "groupBox1");
|
||||
this.groupBox1.Controls.Add(this.autoReconnectCheckBox);
|
||||
this.groupBox1.Controls.Add(this.autoSendClipboardCheckBox);
|
||||
this.groupBox1.Controls.Add(this.remoteKeyboardMapCheckBox);
|
||||
this.groupBox1.Controls.Add(this.swapMouseButtonsCheckBox);
|
||||
@@ -77,6 +79,12 @@
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.TabStop = false;
|
||||
//
|
||||
// autoSendClipboardCheckBox
|
||||
//
|
||||
resources.ApplyResources(this.autoSendClipboardCheckBox, "autoSendClipboardCheckBox");
|
||||
this.autoSendClipboardCheckBox.Name = "autoSendClipboardCheckBox";
|
||||
this.autoSendClipboardCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// remoteKeyboardMapCheckBox
|
||||
//
|
||||
resources.ApplyResources(this.remoteKeyboardMapCheckBox, "remoteKeyboardMapCheckBox");
|
||||
@@ -137,11 +145,11 @@
|
||||
resources.ApplyResources(this.label4, "label4");
|
||||
this.label4.Name = "label4";
|
||||
//
|
||||
// autoSendClipboardCheckBox
|
||||
// autoReconnectCheckBox
|
||||
//
|
||||
resources.ApplyResources(this.autoSendClipboardCheckBox, "autoSendClipboardCheckBox");
|
||||
this.autoSendClipboardCheckBox.Name = "autoSendClipboardCheckBox";
|
||||
this.autoSendClipboardCheckBox.UseVisualStyleBackColor = true;
|
||||
resources.ApplyResources(this.autoReconnectCheckBox, "autoReconnectCheckBox");
|
||||
this.autoReconnectCheckBox.Name = "autoReconnectCheckBox";
|
||||
this.autoReconnectCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// KVMSettingsForm
|
||||
//
|
||||
@@ -182,5 +190,6 @@
|
||||
private System.Windows.Forms.CheckBox swapMouseButtonsCheckBox;
|
||||
private System.Windows.Forms.CheckBox remoteKeyboardMapCheckBox;
|
||||
private System.Windows.Forms.CheckBox autoSendClipboardCheckBox;
|
||||
private System.Windows.Forms.CheckBox autoReconnectCheckBox;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -25,6 +25,7 @@ namespace MeshCentralRouter
|
||||
{
|
||||
InitializeComponent();
|
||||
Translate.TranslateControl(this);
|
||||
qualityComboBox.Items.Add(new DropListItem(100, "100%"));
|
||||
qualityComboBox.Items.Add(new DropListItem(90, "90%"));
|
||||
qualityComboBox.Items.Add(new DropListItem(80, "80%"));
|
||||
qualityComboBox.Items.Add(new DropListItem(70, "70%"));
|
||||
@@ -76,17 +77,18 @@ namespace MeshCentralRouter
|
||||
get { return ((DropListItem)qualityComboBox.SelectedItem).value; }
|
||||
set
|
||||
{
|
||||
if (value >= 90) { qualityComboBox.SelectedIndex = 0; return; }
|
||||
if (value >= 80) { qualityComboBox.SelectedIndex = 1; return; }
|
||||
if (value >= 70) { qualityComboBox.SelectedIndex = 2; return; }
|
||||
if (value >= 60) { qualityComboBox.SelectedIndex = 3; return; }
|
||||
if (value >= 50) { qualityComboBox.SelectedIndex = 4; return; }
|
||||
if (value >= 40) { qualityComboBox.SelectedIndex = 5; return; }
|
||||
if (value >= 30) { qualityComboBox.SelectedIndex = 6; return; }
|
||||
if (value >= 20) { qualityComboBox.SelectedIndex = 7; return; }
|
||||
if (value >= 10) { qualityComboBox.SelectedIndex = 8; return; }
|
||||
if (value >= 5) { qualityComboBox.SelectedIndex = 9; return; }
|
||||
qualityComboBox.SelectedIndex = 10;
|
||||
if (value >= 100) { qualityComboBox.SelectedIndex = 0; return; }
|
||||
if (value >= 90) { qualityComboBox.SelectedIndex = 1; return; }
|
||||
if (value >= 80) { qualityComboBox.SelectedIndex = 2; return; }
|
||||
if (value >= 70) { qualityComboBox.SelectedIndex = 3; return; }
|
||||
if (value >= 60) { qualityComboBox.SelectedIndex = 4; return; }
|
||||
if (value >= 50) { qualityComboBox.SelectedIndex = 5; return; }
|
||||
if (value >= 40) { qualityComboBox.SelectedIndex = 6; return; }
|
||||
if (value >= 30) { qualityComboBox.SelectedIndex = 7; return; }
|
||||
if (value >= 20) { qualityComboBox.SelectedIndex = 8; return; }
|
||||
if (value >= 10) { qualityComboBox.SelectedIndex = 9; return; }
|
||||
if (value >= 5) { qualityComboBox.SelectedIndex = 10; return; }
|
||||
qualityComboBox.SelectedIndex = 11;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,6 +137,12 @@ namespace MeshCentralRouter
|
||||
set { autoSendClipboardCheckBox.Checked = value; }
|
||||
}
|
||||
|
||||
public bool AutoReconnect
|
||||
{
|
||||
get { return autoReconnectCheckBox.Checked; }
|
||||
set { autoReconnectCheckBox.Checked = value; }
|
||||
}
|
||||
|
||||
private void okButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
</data>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="cancelButton.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>312, 254</value>
|
||||
<value>312, 276</value>
|
||||
</data>
|
||||
<data name="cancelButton.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>75, 23</value>
|
||||
@@ -151,7 +151,7 @@
|
||||
<value>Bottom, Right</value>
|
||||
</data>
|
||||
<data name="okButton.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>231, 254</value>
|
||||
<value>231, 276</value>
|
||||
</data>
|
||||
<data name="okButton.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>75, 23</value>
|
||||
@@ -177,6 +177,36 @@
|
||||
<data name="groupBox1.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Bottom, Left, Right</value>
|
||||
</data>
|
||||
<data name="autoReconnectCheckBox.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
</data>
|
||||
<data name="autoReconnectCheckBox.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
|
||||
<value>NoControl</value>
|
||||
</data>
|
||||
<data name="autoReconnectCheckBox.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>128, 174</value>
|
||||
</data>
|
||||
<data name="autoReconnectCheckBox.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>144, 17</value>
|
||||
</data>
|
||||
<data name="autoReconnectCheckBox.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>10</value>
|
||||
</data>
|
||||
<data name="autoReconnectCheckBox.Text" xml:space="preserve">
|
||||
<value>Automatically Reconnect</value>
|
||||
</data>
|
||||
<data name=">>autoReconnectCheckBox.Name" xml:space="preserve">
|
||||
<value>autoReconnectCheckBox</value>
|
||||
</data>
|
||||
<data name=">>autoReconnectCheckBox.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>autoReconnectCheckBox.Parent" xml:space="preserve">
|
||||
<value>groupBox1</value>
|
||||
</data>
|
||||
<data name=">>autoReconnectCheckBox.ZOrder" xml:space="preserve">
|
||||
<value>0</value>
|
||||
</data>
|
||||
<data name="autoSendClipboardCheckBox.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
</data>
|
||||
@@ -205,7 +235,7 @@
|
||||
<value>groupBox1</value>
|
||||
</data>
|
||||
<data name=">>autoSendClipboardCheckBox.ZOrder" xml:space="preserve">
|
||||
<value>0</value>
|
||||
<value>1</value>
|
||||
</data>
|
||||
<data name="remoteKeyboardMapCheckBox.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
@@ -235,7 +265,7 @@
|
||||
<value>groupBox1</value>
|
||||
</data>
|
||||
<data name=">>remoteKeyboardMapCheckBox.ZOrder" xml:space="preserve">
|
||||
<value>1</value>
|
||||
<value>2</value>
|
||||
</data>
|
||||
<data name="swapMouseButtonsCheckBox.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
@@ -262,7 +292,7 @@
|
||||
<value>groupBox1</value>
|
||||
</data>
|
||||
<data name=">>swapMouseButtonsCheckBox.ZOrder" xml:space="preserve">
|
||||
<value>2</value>
|
||||
<value>3</value>
|
||||
</data>
|
||||
<data name="frameRateComboBox.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Left, Right</value>
|
||||
@@ -286,7 +316,7 @@
|
||||
<value>groupBox1</value>
|
||||
</data>
|
||||
<data name=">>frameRateComboBox.ZOrder" xml:space="preserve">
|
||||
<value>3</value>
|
||||
<value>4</value>
|
||||
</data>
|
||||
<data name="label2.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
@@ -313,7 +343,7 @@
|
||||
<value>groupBox1</value>
|
||||
</data>
|
||||
<data name=">>label2.ZOrder" xml:space="preserve">
|
||||
<value>4</value>
|
||||
<value>5</value>
|
||||
</data>
|
||||
<data name="scalingComboBox.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Left, Right</value>
|
||||
@@ -337,7 +367,7 @@
|
||||
<value>groupBox1</value>
|
||||
</data>
|
||||
<data name=">>scalingComboBox.ZOrder" xml:space="preserve">
|
||||
<value>5</value>
|
||||
<value>6</value>
|
||||
</data>
|
||||
<data name="label1.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
@@ -364,7 +394,7 @@
|
||||
<value>groupBox1</value>
|
||||
</data>
|
||||
<data name=">>label1.ZOrder" xml:space="preserve">
|
||||
<value>6</value>
|
||||
<value>7</value>
|
||||
</data>
|
||||
<data name="qualityComboBox.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Left, Right</value>
|
||||
@@ -391,7 +421,7 @@
|
||||
<value>groupBox1</value>
|
||||
</data>
|
||||
<data name=">>qualityComboBox.ZOrder" xml:space="preserve">
|
||||
<value>7</value>
|
||||
<value>8</value>
|
||||
</data>
|
||||
<data name="label3.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
@@ -418,13 +448,13 @@
|
||||
<value>groupBox1</value>
|
||||
</data>
|
||||
<data name=">>label3.ZOrder" xml:space="preserve">
|
||||
<value>8</value>
|
||||
<value>9</value>
|
||||
</data>
|
||||
<data name="groupBox1.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>12, 68</value>
|
||||
</data>
|
||||
<data name="groupBox1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>375, 180</value>
|
||||
<value>375, 202</value>
|
||||
</data>
|
||||
<data name="groupBox1.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>2</value>
|
||||
@@ -502,7 +532,7 @@
|
||||
<value>6, 13</value>
|
||||
</data>
|
||||
<data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
|
||||
<value>399, 289</value>
|
||||
<value>399, 311</value>
|
||||
</data>
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
43
KVMViewer.Designer.cs
generated
43
KVMViewer.Designer.cs
generated
@@ -51,10 +51,11 @@ namespace MeshCentralRouter
|
||||
this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.updateTimer = new System.Windows.Forms.Timer(this.components);
|
||||
this.topPanel = new System.Windows.Forms.Panel();
|
||||
this.extraButtonsPanel = new System.Windows.Forms.Panel();
|
||||
this.splitButton = new System.Windows.Forms.Button();
|
||||
this.clipOutboundButton = new System.Windows.Forms.Button();
|
||||
this.clipInboundButton = new System.Windows.Forms.Button();
|
||||
this.statsButton = new System.Windows.Forms.Button();
|
||||
this.displaySelectComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.settingsButton = new System.Windows.Forms.Button();
|
||||
this.zoomButton = new System.Windows.Forms.Button();
|
||||
this.cadButton = new System.Windows.Forms.Button();
|
||||
@@ -67,6 +68,7 @@ namespace MeshCentralRouter
|
||||
this.consoleTimer = new System.Windows.Forms.Timer(this.components);
|
||||
this.mainToolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.resizeKvmControl = new MeshCentralRouter.KVMResizeControl();
|
||||
this.displaySelectorImageList = new System.Windows.Forms.ImageList(this.components);
|
||||
this.mainStatusStrip.SuspendLayout();
|
||||
this.topPanel.SuspendLayout();
|
||||
this.consentContextMenuStrip.SuspendLayout();
|
||||
@@ -75,6 +77,7 @@ namespace MeshCentralRouter
|
||||
// mainStatusStrip
|
||||
//
|
||||
this.mainStatusStrip.BackColor = System.Drawing.SystemColors.Menu;
|
||||
this.mainStatusStrip.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||
this.mainStatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mainToolStripStatusLabel,
|
||||
this.toolStripStatusLabel1});
|
||||
@@ -101,10 +104,11 @@ namespace MeshCentralRouter
|
||||
// topPanel
|
||||
//
|
||||
this.topPanel.BackColor = System.Drawing.SystemColors.Control;
|
||||
this.topPanel.Controls.Add(this.extraButtonsPanel);
|
||||
this.topPanel.Controls.Add(this.splitButton);
|
||||
this.topPanel.Controls.Add(this.clipOutboundButton);
|
||||
this.topPanel.Controls.Add(this.clipInboundButton);
|
||||
this.topPanel.Controls.Add(this.statsButton);
|
||||
this.topPanel.Controls.Add(this.displaySelectComboBox);
|
||||
this.topPanel.Controls.Add(this.settingsButton);
|
||||
this.topPanel.Controls.Add(this.zoomButton);
|
||||
this.topPanel.Controls.Add(this.cadButton);
|
||||
@@ -112,6 +116,19 @@ namespace MeshCentralRouter
|
||||
resources.ApplyResources(this.topPanel, "topPanel");
|
||||
this.topPanel.Name = "topPanel";
|
||||
//
|
||||
// extraButtonsPanel
|
||||
//
|
||||
resources.ApplyResources(this.extraButtonsPanel, "extraButtonsPanel");
|
||||
this.extraButtonsPanel.Name = "extraButtonsPanel";
|
||||
//
|
||||
// splitButton
|
||||
//
|
||||
resources.ApplyResources(this.splitButton, "splitButton");
|
||||
this.splitButton.Name = "splitButton";
|
||||
this.splitButton.TabStop = false;
|
||||
this.splitButton.UseVisualStyleBackColor = true;
|
||||
this.splitButton.Click += new System.EventHandler(this.splitButton_Click);
|
||||
//
|
||||
// clipOutboundButton
|
||||
//
|
||||
resources.ApplyResources(this.clipOutboundButton, "clipOutboundButton");
|
||||
@@ -139,14 +156,6 @@ namespace MeshCentralRouter
|
||||
this.statsButton.UseVisualStyleBackColor = true;
|
||||
this.statsButton.Click += new System.EventHandler(this.statsButton_Click);
|
||||
//
|
||||
// displaySelectComboBox
|
||||
//
|
||||
this.displaySelectComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
resources.ApplyResources(this.displaySelectComboBox, "displaySelectComboBox");
|
||||
this.displaySelectComboBox.Name = "displaySelectComboBox";
|
||||
this.displaySelectComboBox.TabStop = false;
|
||||
this.displaySelectComboBox.SelectionChangeCommitted += new System.EventHandler(this.displaySelectComboBox_SelectionChangeCommitted);
|
||||
//
|
||||
// settingsButton
|
||||
//
|
||||
resources.ApplyResources(this.settingsButton, "settingsButton");
|
||||
@@ -183,6 +192,7 @@ namespace MeshCentralRouter
|
||||
//
|
||||
// consentContextMenuStrip
|
||||
//
|
||||
this.consentContextMenuStrip.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||
this.consentContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.askConsentBarToolStripMenuItem,
|
||||
this.askConsentToolStripMenuItem,
|
||||
@@ -231,6 +241,15 @@ namespace MeshCentralRouter
|
||||
this.resizeKvmControl.Enter += new System.EventHandler(this.resizeKvmControl_Enter);
|
||||
this.resizeKvmControl.Leave += new System.EventHandler(this.resizeKvmControl_Leave);
|
||||
//
|
||||
// displaySelectorImageList
|
||||
//
|
||||
this.displaySelectorImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("displaySelectorImageList.ImageStream")));
|
||||
this.displaySelectorImageList.TransparentColor = System.Drawing.Color.Transparent;
|
||||
this.displaySelectorImageList.Images.SetKeyName(0, "icon-monitor1.png");
|
||||
this.displaySelectorImageList.Images.SetKeyName(1, "icon-monitor1b.png");
|
||||
this.displaySelectorImageList.Images.SetKeyName(2, "icon-monitor2.png");
|
||||
this.displaySelectorImageList.Images.SetKeyName(3, "icon-monitor2b.png");
|
||||
//
|
||||
// KVMViewer
|
||||
//
|
||||
resources.ApplyResources(this, "$this");
|
||||
@@ -266,7 +285,6 @@ namespace MeshCentralRouter
|
||||
private Button cadButton;
|
||||
private Button zoomButton;
|
||||
private Button settingsButton;
|
||||
private ComboBox displaySelectComboBox;
|
||||
private Label consoleMessage;
|
||||
private Timer consoleTimer;
|
||||
private Button statsButton;
|
||||
@@ -277,6 +295,9 @@ namespace MeshCentralRouter
|
||||
private ToolStripMenuItem askConsentBarToolStripMenuItem;
|
||||
private ToolStripMenuItem askConsentToolStripMenuItem;
|
||||
private ToolStripMenuItem privacyBarToolStripMenuItem;
|
||||
private Button splitButton;
|
||||
private Panel extraButtonsPanel;
|
||||
private ImageList displaySelectorImageList;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
182
KVMViewer.cs
182
KVMViewer.cs
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,6 @@ using System.Windows.Forms;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.Web.Script.Serialization;
|
||||
using Microsoft.Win32;
|
||||
using System.Threading;
|
||||
|
||||
namespace MeshCentralRouter
|
||||
@@ -42,6 +41,11 @@ namespace MeshCentralRouter
|
||||
private string lastClipboardSent = null;
|
||||
private DateTime lastClipboardTime = DateTime.MinValue;
|
||||
public string lang = Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName;
|
||||
private bool splitMode = false;
|
||||
private KVMViewerExtra[] extraDisplays = null;
|
||||
private System.Windows.Forms.Timer delayedConnectionTimer = null;
|
||||
private bool localAutoReconnect = true;
|
||||
private Dictionary<int, Button> displaySelectionButtons = new Dictionary<int, Button>();
|
||||
|
||||
// Stats
|
||||
public long bytesIn = 0;
|
||||
@@ -49,16 +53,6 @@ namespace MeshCentralRouter
|
||||
public long bytesOut = 0;
|
||||
public long bytesOutCompressed = 0;
|
||||
|
||||
public class displayTag
|
||||
{
|
||||
public ushort num;
|
||||
public string name;
|
||||
|
||||
public displayTag(ushort num, string name) { this.num = num; this.name = name; }
|
||||
|
||||
public override string ToString() { return name; }
|
||||
}
|
||||
|
||||
public KVMViewer(MainForm parent, MeshCentralServer server, NodeClass node)
|
||||
{
|
||||
this.parent = parent;
|
||||
@@ -70,6 +64,7 @@ namespace MeshCentralRouter
|
||||
kvmControl = resizeKvmControl.KVM;
|
||||
kvmControl.parent = this;
|
||||
kvmControl.DesktopSizeChanged += KvmControl_DesktopSizeChanged;
|
||||
kvmControl.ScreenAreaUpdated += KvmControl_ScreenAreaUpdated;
|
||||
resizeKvmControl.ZoomToFit = true;
|
||||
UpdateStatus();
|
||||
this.MouseWheel += MainForm_MouseWheel;
|
||||
@@ -82,7 +77,27 @@ namespace MeshCentralRouter
|
||||
mainToolTip.SetToolTip(clipInboundButton, Translate.T(Properties.Resources.PullClipboardFromRemoteDevice, lang));
|
||||
mainToolTip.SetToolTip(zoomButton, Translate.T(Properties.Resources.ToggleZoomToFitMode, lang));
|
||||
mainToolTip.SetToolTip(statsButton, Translate.T(Properties.Resources.DisplayConnectionStatistics, lang));
|
||||
|
||||
// Load remote desktop settings
|
||||
int CompressionLevel = 60;
|
||||
try { CompressionLevel = int.Parse(Settings.GetRegValue("kvmCompression", "60")); } catch (Exception) { }
|
||||
int ScalingLevel = 1024;
|
||||
try { ScalingLevel = int.Parse(Settings.GetRegValue("kvmScaling", "1024")); } catch (Exception) { }
|
||||
int FrameRate = 100;
|
||||
try { FrameRate = int.Parse(Settings.GetRegValue("kvmFrameRate", "100")); } catch (Exception) { }
|
||||
kvmControl.SetCompressionParams(CompressionLevel, ScalingLevel, FrameRate);
|
||||
kvmControl.SwamMouseButtons = Settings.GetRegValue("kvmSwamMouseButtons", "0").Equals("1");
|
||||
kvmControl.RemoteKeyboardMap = Settings.GetRegValue("kvmSwamMouseButtons", "0").Equals("1");
|
||||
kvmControl.AutoSendClipboard = Settings.GetRegValue("kvmAutoClipboard", "0").Equals("1");
|
||||
kvmControl.AutoReconnect = Settings.GetRegValue("kvmAutoReconnect", "0").Equals("1");
|
||||
}
|
||||
|
||||
private void KvmControl_ScreenAreaUpdated(Bitmap desktop, Rectangle r)
|
||||
{
|
||||
if (extraDisplays == null) return;
|
||||
foreach (KVMViewerExtra x in extraDisplays) {
|
||||
if (x != null) { x.UpdateScreenArea(desktop, r); }
|
||||
}
|
||||
}
|
||||
|
||||
private void Parent_ClipboardChanged()
|
||||
@@ -107,6 +122,25 @@ namespace MeshCentralRouter
|
||||
}
|
||||
}
|
||||
|
||||
public void TryAutoConnect()
|
||||
{
|
||||
if ((localAutoReconnect == false) || (kvmControl.AutoReconnect == false)) return;
|
||||
if ((state == 0) && (wc == null) && (delayedConnectionTimer == null)) {
|
||||
// Hold half a second before trying to connect
|
||||
delayedConnectionTimer = new System.Windows.Forms.Timer(this.components);
|
||||
delayedConnectionTimer.Tick += new EventHandler(updateTimerTick);
|
||||
delayedConnectionTimer.Interval = 500;
|
||||
delayedConnectionTimer.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTimerTick(object sender, EventArgs e)
|
||||
{
|
||||
delayedConnectionTimer.Dispose();
|
||||
delayedConnectionTimer = null;
|
||||
if ((state == 0) && (wc == null)) { MenuItemConnect_Click(this, null); }
|
||||
}
|
||||
|
||||
private void KvmControl_DesktopSizeChanged(object sender, EventArgs e)
|
||||
{
|
||||
kvmControl.Visible = true;
|
||||
@@ -184,7 +218,8 @@ namespace MeshCentralRouter
|
||||
wc.onStateChanged += Wc_onStateChanged;
|
||||
wc.onBinaryData += Wc_onBinaryData;
|
||||
wc.onStringData += Wc_onStringData;
|
||||
wc.Start(u, server.wshash);
|
||||
wc.TLSCertCheck = webSocketClient.TLSCertificateCheck.Fingerprint;
|
||||
wc.Start(u, server.wshash, null);
|
||||
}
|
||||
|
||||
private void Wc_onStateChanged(webSocketClient sender, webSocketClient.ConnectionStates wsstate)
|
||||
@@ -301,10 +336,13 @@ namespace MeshCentralRouter
|
||||
if (wc != null)
|
||||
{
|
||||
// Disconnect
|
||||
if (splitMode) { splitButton_Click(this, null); }
|
||||
splitButton.Visible = false;
|
||||
state = 0;
|
||||
wc.Dispose();
|
||||
wc = null;
|
||||
UpdateStatus();
|
||||
localAutoReconnect = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -312,6 +350,7 @@ namespace MeshCentralRouter
|
||||
if (sender != null) { consentFlags = 0; }
|
||||
MenuItemConnect_Click(null, null);
|
||||
kvmControl.AttachKeyboard();
|
||||
localAutoReconnect = true;
|
||||
}
|
||||
displayMessage(null);
|
||||
}
|
||||
@@ -328,7 +367,7 @@ namespace MeshCentralRouter
|
||||
{
|
||||
case 0: // Disconnected
|
||||
mainToolStripStatusLabel.Text = Translate.T(Properties.Resources.Disconnected, lang);
|
||||
displaySelectComboBox.Visible = false;
|
||||
extraButtonsPanel.Visible = false;
|
||||
kvmControl.Visible = false;
|
||||
kvmControl.screenWidth = 0;
|
||||
kvmControl.screenHeight = 0;
|
||||
@@ -336,13 +375,13 @@ namespace MeshCentralRouter
|
||||
break;
|
||||
case 1: // Connecting
|
||||
mainToolStripStatusLabel.Text = Translate.T(Properties.Resources.Connecting, lang);
|
||||
displaySelectComboBox.Visible = false;
|
||||
extraButtonsPanel.Visible = false;
|
||||
kvmControl.Visible = false;
|
||||
connectButton.Text = Translate.T(Properties.Resources.Disconnect, lang);
|
||||
break;
|
||||
case 2: // Setup
|
||||
mainToolStripStatusLabel.Text = "Setup...";
|
||||
displaySelectComboBox.Visible = false;
|
||||
extraButtonsPanel.Visible = false;
|
||||
kvmControl.Visible = false;
|
||||
connectButton.Text = Translate.T(Properties.Resources.Disconnect, lang);
|
||||
break;
|
||||
@@ -392,6 +431,9 @@ namespace MeshCentralRouter
|
||||
|
||||
// Save window location
|
||||
Settings.SetRegValue("kvmlocation", Location.X + "," + Location.Y + "," + Size.Width + "," + Size.Height);
|
||||
|
||||
// Close any extra windows
|
||||
extraScreenClosed();
|
||||
}
|
||||
|
||||
private void toolStripMenuItem2_DropDownOpening(object sender, EventArgs e)
|
||||
@@ -418,11 +460,21 @@ namespace MeshCentralRouter
|
||||
form.SwamMouseButtons = kvmControl.SwamMouseButtons;
|
||||
form.RemoteKeyboardMap = kvmControl.RemoteKeyboardMap;
|
||||
form.AutoSendClipboard = kvmControl.AutoSendClipboard;
|
||||
form.AutoReconnect = kvmControl.AutoReconnect;
|
||||
if (form.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
|
||||
{
|
||||
kvmControl.SetCompressionParams(form.Compression, form.Scaling, form.FrameRate);
|
||||
kvmControl.SwamMouseButtons = form.SwamMouseButtons;
|
||||
kvmControl.RemoteKeyboardMap = form.RemoteKeyboardMap;
|
||||
kvmControl.AutoReconnect = form.AutoReconnect;
|
||||
|
||||
Settings.SetRegValue("kvmCompression", kvmControl.CompressionLevel.ToString());
|
||||
Settings.SetRegValue("kvmScaling", kvmControl.ScalingLevel.ToString());
|
||||
Settings.SetRegValue("kvmFrameRate", kvmControl.FrameRate.ToString());
|
||||
Settings.SetRegValue("kvmSwamMouseButtons", kvmControl.SwamMouseButtons ? "1" : "0");
|
||||
Settings.SetRegValue("kvmRemoteKeyboardMap", kvmControl.RemoteKeyboardMap ? "1" : "0");
|
||||
Settings.SetRegValue("kvmAutoReconnect", kvmControl.AutoReconnect ? "1" : "0");
|
||||
|
||||
if (kvmControl.AutoSendClipboard != form.AutoSendClipboard)
|
||||
{
|
||||
kvmControl.AutoSendClipboard = form.AutoSendClipboard;
|
||||
@@ -454,41 +506,70 @@ namespace MeshCentralRouter
|
||||
resizeKvmControl.ZoomToFit = !resizeKvmControl.ZoomToFit;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void resizeKvmControl_DisplaysReceived(object sender, EventArgs e)
|
||||
{
|
||||
if (kvmControl == null || kvmControl.displays.Count == 0) return;
|
||||
|
||||
if (kvmControl.displays.Count > 0)
|
||||
{
|
||||
displaySelectComboBox.Visible = true;
|
||||
displaySelectComboBox.Items.Clear();
|
||||
extraButtonsPanel.Visible = true;
|
||||
extraButtonsPanel.Controls.Clear();
|
||||
displaySelectionButtons.Clear();
|
||||
foreach (ushort displayNum in kvmControl.displays)
|
||||
{
|
||||
displayTag t;
|
||||
if (displayNum == 0xFFFF)
|
||||
{
|
||||
t = new displayTag(displayNum, Translate.T(Properties.Resources.AllDisplays, lang));
|
||||
displaySelectComboBox.Items.Add(t);
|
||||
Button b = new Button();
|
||||
b.ImageList = displaySelectorImageList;
|
||||
b.ImageIndex = (kvmControl.currentDisp == displayNum) ? 2 : 3; // All displayes
|
||||
b.Width = 32;
|
||||
b.Height = 32;
|
||||
mainToolTip.SetToolTip(b, Translate.T(Properties.Resources.AllDisplays, lang));
|
||||
b.Click += new System.EventHandler(this.displaySelectComboBox_SelectionChangeCommitted);
|
||||
b.Tag = displayNum;
|
||||
b.Dock = DockStyle.Left;
|
||||
extraButtonsPanel.Controls.Add(b);
|
||||
displaySelectionButtons.Add(displayNum, b);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = new displayTag(displayNum, string.Format(Translate.T(Properties.Resources.DisplayX, lang), displayNum));
|
||||
displaySelectComboBox.Items.Add(t);
|
||||
Button b = new Button();
|
||||
b.ImageList = displaySelectorImageList;
|
||||
b.ImageIndex = (kvmControl.currentDisp == displayNum) ? 0 : 1; // One display grayed out
|
||||
b.Width = 32;
|
||||
b.Height = 32;
|
||||
mainToolTip.SetToolTip(b, string.Format(Translate.T(Properties.Resources.DisplayX, lang), displayNum));
|
||||
b.Click += new System.EventHandler(this.displaySelectComboBox_SelectionChangeCommitted);
|
||||
b.Tag = displayNum;
|
||||
b.Dock = DockStyle.Left;
|
||||
extraButtonsPanel.Controls.Add(b);
|
||||
displaySelectionButtons.Add(displayNum, b);
|
||||
}
|
||||
|
||||
if (kvmControl.currentDisp == displayNum) { displaySelectComboBox.SelectedItem = t; }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
displaySelectComboBox.Visible = false;
|
||||
displaySelectComboBox.Items.Clear();
|
||||
extraButtonsPanel.Visible = false;
|
||||
extraButtonsPanel.Controls.Clear();
|
||||
displaySelectionButtons.Clear();
|
||||
}
|
||||
|
||||
// If there are many displays and all displays is selected, enable split/join button.
|
||||
splitButton.Visible = ((kvmControl.currentDisp == 65535) && (kvmControl.displays.Count > 1));
|
||||
}
|
||||
|
||||
private void displaySelectComboBox_SelectionChangeCommitted(object sender, EventArgs e)
|
||||
{
|
||||
if (kvmControl != null) kvmControl.SendDisplay(((displayTag)displaySelectComboBox.SelectedItem).num);
|
||||
if (splitMode) { splitButton_Click(this, null); }
|
||||
if (kvmControl != null) {
|
||||
ushort displayNum = (ushort)((Button)sender).Tag;
|
||||
kvmControl.SendDisplay(displayNum);
|
||||
}
|
||||
}
|
||||
|
||||
private void resizeKvmControl_TouchEnabledChanged(object sender, EventArgs e)
|
||||
@@ -630,5 +711,50 @@ namespace MeshCentralRouter
|
||||
{
|
||||
if (wc != null) { e.Cancel = true; }
|
||||
}
|
||||
|
||||
public void extraScreenClosed()
|
||||
{
|
||||
if (splitMode) { splitButton_Click(this, null); }
|
||||
}
|
||||
|
||||
private void splitButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (splitMode)
|
||||
{
|
||||
kvmControl.cropDisplay(Point.Empty, Rectangle.Empty);
|
||||
splitButton.Text = Translate.T(Properties.Resources.Split, lang);
|
||||
splitMode = false;
|
||||
if (extraDisplays != null)
|
||||
{
|
||||
// Close all extra displays
|
||||
for (int i = 0; i < extraDisplays.Length; i++)
|
||||
{
|
||||
KVMViewerExtra extraDisplay = extraDisplays[i];
|
||||
extraDisplay.Close();
|
||||
}
|
||||
extraDisplays = null;
|
||||
}
|
||||
}
|
||||
else if ((kvmControl.displayInfo != null) && (kvmControl.displayInfo.Length > 1))
|
||||
{
|
||||
int minx = 0;
|
||||
int miny = 0;
|
||||
foreach (Rectangle r in kvmControl.displayInfo) { if (r.X < minx) { minx = r.X; } if (r.Y < miny) { miny = r.Y; } }
|
||||
kvmControl.cropDisplay(new Point(minx, miny), kvmControl.displayInfo[0]);
|
||||
splitButton.Text = Translate.T(Properties.Resources.Join, lang);
|
||||
splitMode = true;
|
||||
|
||||
// Open extra displays
|
||||
extraDisplays = new KVMViewerExtra[kvmControl.displayInfo.Length - 1];
|
||||
for (int i = 1; i < kvmControl.displayInfo.Length; i++)
|
||||
{
|
||||
KVMViewerExtra extraDisplay = new KVMViewerExtra(parent, this, node, kvmControl, i);
|
||||
extraDisplays[i - 1] = extraDisplay;
|
||||
extraDisplay.Show(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
278
KVMViewer.resx
278
KVMViewer.resx
@@ -122,7 +122,7 @@
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="mainToolStripStatusLabel.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>1029, 17</value>
|
||||
<value>1372, 20</value>
|
||||
</data>
|
||||
<data name="mainToolStripStatusLabel.Text" xml:space="preserve">
|
||||
<value>---</value>
|
||||
@@ -131,7 +131,7 @@
|
||||
<value>MiddleLeft</value>
|
||||
</data>
|
||||
<data name="toolStripStatusLabel1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>13, 17</value>
|
||||
<value>16, 20</value>
|
||||
</data>
|
||||
<data name="toolStripStatusLabel1.Text" xml:space="preserve">
|
||||
<value>v</value>
|
||||
@@ -141,10 +141,14 @@
|
||||
<value>False</value>
|
||||
</data>
|
||||
<data name="mainStatusStrip.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>0, 727</value>
|
||||
<value>0, 897</value>
|
||||
</data>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="mainStatusStrip.Padding" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>1, 0, 19, 0</value>
|
||||
</data>
|
||||
<data name="mainStatusStrip.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>1044, 22</value>
|
||||
<value>1392, 25</value>
|
||||
</data>
|
||||
<data name="mainStatusStrip.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>9</value>
|
||||
@@ -167,7 +171,66 @@
|
||||
<metadata name="updateTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>154, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="extraButtonsPanel.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Left, Right</value>
|
||||
</data>
|
||||
<data name="extraButtonsPanel.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>383, 4</value>
|
||||
</data>
|
||||
<data name="extraButtonsPanel.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>658, 32</value>
|
||||
</data>
|
||||
<data name="extraButtonsPanel.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>10</value>
|
||||
</data>
|
||||
<data name=">>extraButtonsPanel.Name" xml:space="preserve">
|
||||
<value>extraButtonsPanel</value>
|
||||
</data>
|
||||
<data name=">>extraButtonsPanel.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>extraButtonsPanel.Parent" xml:space="preserve">
|
||||
<value>topPanel</value>
|
||||
</data>
|
||||
<data name=">>extraButtonsPanel.ZOrder" xml:space="preserve">
|
||||
<value>0</value>
|
||||
</data>
|
||||
<data name="splitButton.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Right</value>
|
||||
</data>
|
||||
<data name="splitButton.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
|
||||
<value>NoControl</value>
|
||||
</data>
|
||||
<data name="splitButton.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>1048, 4</value>
|
||||
</data>
|
||||
<data name="splitButton.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>4, 4, 4, 4</value>
|
||||
</data>
|
||||
<data name="splitButton.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>119, 32</value>
|
||||
</data>
|
||||
<data name="splitButton.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>8</value>
|
||||
</data>
|
||||
<data name="splitButton.Text" xml:space="preserve">
|
||||
<value>Split</value>
|
||||
</data>
|
||||
<data name="splitButton.Visible" type="System.Boolean, mscorlib">
|
||||
<value>False</value>
|
||||
</data>
|
||||
<data name=">>splitButton.Name" xml:space="preserve">
|
||||
<value>splitButton</value>
|
||||
</data>
|
||||
<data name=">>splitButton.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>splitButton.Parent" xml:space="preserve">
|
||||
<value>topPanel</value>
|
||||
</data>
|
||||
<data name=">>splitButton.ZOrder" xml:space="preserve">
|
||||
<value>1</value>
|
||||
</data>
|
||||
<data name="clipOutboundButton.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Right</value>
|
||||
</data>
|
||||
@@ -178,10 +241,13 @@
|
||||
<value>NoControl</value>
|
||||
</data>
|
||||
<data name="clipOutboundButton.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>881, 3</value>
|
||||
<value>1175, 4</value>
|
||||
</data>
|
||||
<data name="clipOutboundButton.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>4, 4, 4, 4</value>
|
||||
</data>
|
||||
<data name="clipOutboundButton.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>30, 26</value>
|
||||
<value>40, 32</value>
|
||||
</data>
|
||||
<data name="clipOutboundButton.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>3</value>
|
||||
@@ -196,7 +262,7 @@
|
||||
<value>topPanel</value>
|
||||
</data>
|
||||
<data name=">>clipOutboundButton.ZOrder" xml:space="preserve">
|
||||
<value>0</value>
|
||||
<value>2</value>
|
||||
</data>
|
||||
<data name="clipInboundButton.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Right</value>
|
||||
@@ -208,10 +274,13 @@
|
||||
<value>NoControl</value>
|
||||
</data>
|
||||
<data name="clipInboundButton.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>917, 3</value>
|
||||
<value>1223, 4</value>
|
||||
</data>
|
||||
<data name="clipInboundButton.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>4, 4, 4, 4</value>
|
||||
</data>
|
||||
<data name="clipInboundButton.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>30, 26</value>
|
||||
<value>40, 32</value>
|
||||
</data>
|
||||
<data name="clipInboundButton.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>4</value>
|
||||
@@ -232,7 +301,7 @@
|
||||
<value>topPanel</value>
|
||||
</data>
|
||||
<data name=">>clipInboundButton.ZOrder" xml:space="preserve">
|
||||
<value>1</value>
|
||||
<value>3</value>
|
||||
</data>
|
||||
<data name="statsButton.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Right</value>
|
||||
@@ -241,10 +310,13 @@
|
||||
<value>NoControl</value>
|
||||
</data>
|
||||
<data name="statsButton.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>989, 3</value>
|
||||
<value>1319, 4</value>
|
||||
</data>
|
||||
<data name="statsButton.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>4, 4, 4, 4</value>
|
||||
</data>
|
||||
<data name="statsButton.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>52, 26</value>
|
||||
<value>69, 32</value>
|
||||
</data>
|
||||
<data name="statsButton.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>7</value>
|
||||
@@ -262,43 +334,19 @@
|
||||
<value>topPanel</value>
|
||||
</data>
|
||||
<data name=">>statsButton.ZOrder" xml:space="preserve">
|
||||
<value>2</value>
|
||||
</data>
|
||||
<data name="displaySelectComboBox.ItemHeight" type="System.Int32, mscorlib">
|
||||
<value>13</value>
|
||||
</data>
|
||||
<data name="displaySelectComboBox.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>288, 5</value>
|
||||
</data>
|
||||
<data name="displaySelectComboBox.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>128, 21</value>
|
||||
</data>
|
||||
<data name="displaySelectComboBox.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>5</value>
|
||||
</data>
|
||||
<data name="displaySelectComboBox.Visible" type="System.Boolean, mscorlib">
|
||||
<value>False</value>
|
||||
</data>
|
||||
<data name=">>displaySelectComboBox.Name" xml:space="preserve">
|
||||
<value>displaySelectComboBox</value>
|
||||
</data>
|
||||
<data name=">>displaySelectComboBox.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>displaySelectComboBox.Parent" xml:space="preserve">
|
||||
<value>topPanel</value>
|
||||
</data>
|
||||
<data name=">>displaySelectComboBox.ZOrder" xml:space="preserve">
|
||||
<value>3</value>
|
||||
<value>4</value>
|
||||
</data>
|
||||
<data name="settingsButton.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
|
||||
<value>NoControl</value>
|
||||
</data>
|
||||
<data name="settingsButton.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>193, 3</value>
|
||||
<value>257, 4</value>
|
||||
</data>
|
||||
<data name="settingsButton.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>4, 4, 4, 4</value>
|
||||
</data>
|
||||
<data name="settingsButton.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>89, 26</value>
|
||||
<value>119, 32</value>
|
||||
</data>
|
||||
<data name="settingsButton.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>2</value>
|
||||
@@ -316,7 +364,7 @@
|
||||
<value>topPanel</value>
|
||||
</data>
|
||||
<data name=">>settingsButton.ZOrder" xml:space="preserve">
|
||||
<value>4</value>
|
||||
<value>5</value>
|
||||
</data>
|
||||
<data name="zoomButton.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Right</value>
|
||||
@@ -325,10 +373,13 @@
|
||||
<value>NoControl</value>
|
||||
</data>
|
||||
<data name="zoomButton.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>953, 3</value>
|
||||
<value>1271, 4</value>
|
||||
</data>
|
||||
<data name="zoomButton.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>4, 4, 4, 4</value>
|
||||
</data>
|
||||
<data name="zoomButton.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>30, 26</value>
|
||||
<value>40, 32</value>
|
||||
</data>
|
||||
<data name="zoomButton.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>6</value>
|
||||
@@ -343,7 +394,7 @@
|
||||
<value>topPanel</value>
|
||||
</data>
|
||||
<data name=">>zoomButton.ZOrder" xml:space="preserve">
|
||||
<value>5</value>
|
||||
<value>6</value>
|
||||
</data>
|
||||
<data name="cadButton.Enabled" type="System.Boolean, mscorlib">
|
||||
<value>False</value>
|
||||
@@ -352,10 +403,13 @@
|
||||
<value>NoControl</value>
|
||||
</data>
|
||||
<data name="cadButton.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>98, 3</value>
|
||||
<value>131, 4</value>
|
||||
</data>
|
||||
<data name="cadButton.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>4, 4, 4, 4</value>
|
||||
</data>
|
||||
<data name="cadButton.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>89, 26</value>
|
||||
<value>119, 32</value>
|
||||
</data>
|
||||
<data name="cadButton.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>1</value>
|
||||
@@ -373,31 +427,31 @@
|
||||
<value>topPanel</value>
|
||||
</data>
|
||||
<data name=">>cadButton.ZOrder" xml:space="preserve">
|
||||
<value>6</value>
|
||||
<value>7</value>
|
||||
</data>
|
||||
<metadata name="consentContextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>518, 17</value>
|
||||
</metadata>
|
||||
<data name="askConsentBarToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>171, 22</value>
|
||||
<value>198, 24</value>
|
||||
</data>
|
||||
<data name="askConsentBarToolStripMenuItem.Text" xml:space="preserve">
|
||||
<value>Ask Consent + Bar</value>
|
||||
</data>
|
||||
<data name="askConsentToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>171, 22</value>
|
||||
<value>198, 24</value>
|
||||
</data>
|
||||
<data name="askConsentToolStripMenuItem.Text" xml:space="preserve">
|
||||
<value>Ask Consent</value>
|
||||
</data>
|
||||
<data name="privacyBarToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>171, 22</value>
|
||||
<value>198, 24</value>
|
||||
</data>
|
||||
<data name="privacyBarToolStripMenuItem.Text" xml:space="preserve">
|
||||
<value>Privacy Bar</value>
|
||||
</data>
|
||||
<data name="consentContextMenuStrip.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>172, 70</value>
|
||||
<value>199, 76</value>
|
||||
</data>
|
||||
<data name=">>consentContextMenuStrip.Name" xml:space="preserve">
|
||||
<value>consentContextMenuStrip</value>
|
||||
@@ -409,10 +463,13 @@
|
||||
<value>NoControl</value>
|
||||
</data>
|
||||
<data name="connectButton.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>3, 3</value>
|
||||
<value>4, 4</value>
|
||||
</data>
|
||||
<data name="connectButton.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>4, 4, 4, 4</value>
|
||||
</data>
|
||||
<data name="connectButton.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>89, 26</value>
|
||||
<value>119, 32</value>
|
||||
</data>
|
||||
<data name="connectButton.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>0</value>
|
||||
@@ -430,7 +487,7 @@
|
||||
<value>topPanel</value>
|
||||
</data>
|
||||
<data name=">>connectButton.ZOrder" xml:space="preserve">
|
||||
<value>7</value>
|
||||
<value>8</value>
|
||||
</data>
|
||||
<data name="topPanel.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
|
||||
<value>Top</value>
|
||||
@@ -438,8 +495,11 @@
|
||||
<data name="topPanel.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>0, 0</value>
|
||||
</data>
|
||||
<data name="topPanel.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>4, 4, 4, 4</value>
|
||||
</data>
|
||||
<data name="topPanel.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>1044, 32</value>
|
||||
<value>1392, 39</value>
|
||||
</data>
|
||||
<data name="topPanel.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>11</value>
|
||||
@@ -469,10 +529,13 @@
|
||||
<value>NoControl</value>
|
||||
</data>
|
||||
<data name="consoleMessage.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>12, 59</value>
|
||||
<value>16, 73</value>
|
||||
</data>
|
||||
<data name="consoleMessage.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>4, 0, 4, 0</value>
|
||||
</data>
|
||||
<data name="consoleMessage.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>70, 25</value>
|
||||
<value>86, 31</value>
|
||||
</data>
|
||||
<data name="consoleMessage.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>12</value>
|
||||
@@ -502,10 +565,13 @@
|
||||
<value>Fill</value>
|
||||
</data>
|
||||
<data name="resizeKvmControl.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>0, 32</value>
|
||||
<value>0, 39</value>
|
||||
</data>
|
||||
<data name="resizeKvmControl.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>4, 4, 4, 4</value>
|
||||
</data>
|
||||
<data name="resizeKvmControl.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>1044, 695</value>
|
||||
<value>1392, 858</value>
|
||||
</data>
|
||||
<data name="resizeKvmControl.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>10</value>
|
||||
@@ -514,7 +580,7 @@
|
||||
<value>resizeKvmControl</value>
|
||||
</data>
|
||||
<data name=">>resizeKvmControl.Type" xml:space="preserve">
|
||||
<value>MeshCentralRouter.KVMResizeControl, MeshCentralRouter, Version=1.7.7835.29677, Culture=neutral, PublicKeyToken=null</value>
|
||||
<value>MeshCentralRouter.KVMResizeControl, MeshCentralRouter, Version=1.8.8096.29519, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
<data name=">>resizeKvmControl.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
@@ -522,14 +588,88 @@
|
||||
<data name=">>resizeKvmControl.ZOrder" xml:space="preserve">
|
||||
<value>2</value>
|
||||
</data>
|
||||
<metadata name="displaySelectorImageList.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>752, 17</value>
|
||||
</metadata>
|
||||
<data name="displaySelectorImageList.ImageStream" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>
|
||||
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
|
||||
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
|
||||
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADs
|
||||
DgAAAk1TRnQBSQFMAgEBBAEAARABAAEQAQABEAEAARABAAT/AREBAAj/AUIBTQE2BwABNgMAASgDAAFA
|
||||
AwABIAMAAQEBAAEQBgABEP8A/wD/AP8A/wD/AP8A/wAiAAH3AV4BpQEUAaUBFAGlARQBpQEUAaUBFAGl
|
||||
ARQB9wFeEAAB9wFeAaUBFAGlARQBpQEUAaUBFAGlARQBpQEUAfcBXhAAAfcBXgGlARQBpQEUAaUBFAGl
|
||||
ARQBpQEUAaUBFAH3AV4QAAH3AV4BpQEUAaUBFAGlARQBpQEUAaUBFAGlARQB9wFeEAAB3gF7ARgBYwFr
|
||||
AS0BYwEQAYQBEAFrAS0BGAFjAd4BexAAAd4BewEYAWMBawEtAYQBEAGEARABawEtARgBYwHeAXsQAAHe
|
||||
AXsBGAFjAWsBLQFjARABhAEQAWsBLQEYAWMB3gF7EAAB3gF7ARgBYwFrAS0BhAEQAYQBEAFrAS0BGAFj
|
||||
Ad4BexQAAXsBbwFkARABZAEQAVoBaxgAAXsBbwFjAQwBYwEMAVoBaxgAAXsBbwFkARABZAEQAVoBaxgA
|
||||
AXsBbwFjAQwBYwEMAVoBawwAAZwBcwH3AV4B9wFeAfcBXgH3AV4B9wFeAWsBLQFiARABYgEQAWoBLQH3
|
||||
AV4B9wFeAfcBXgH3AV4B9wFeAZwBcwGcAXMB9wFeAfcBXgH3AV4B9wFeAfcBXgFrAS0BYwEMAWMBDAFr
|
||||
AS0B9wFeAfcBXgH3AV4B9wFeAfcBXgGcAXMBnAFzAfcBXgH3AV4B9wFeAfcBXgH3AV4BawEtAWIBEAFi
|
||||
ARABagEtAfcBXgH3AV4B9wFeAfcBXgH3AV4BnAFzAZwBcwH3AV4B9wFeAfcBXgH3AV4B9wFeAWsBLQFj
|
||||
AQwBYwEMAWsBLQH3AV4B9wFeAfcBXgH3AV4B9wFeAZwBcwErARkB2gEeAdoBHgHaAR4B2gEeAdoBHgHa
|
||||
AR4B2wEeAdsBHgHbAR4BugEeAboBHgHaAR4BugEeAdoBHgFMARkBCAEhAVIBSgFSAUoBUgFKAVIBSgFS
|
||||
AUoBUgFKAVIBSgFSAUoBUgFKAVIBSgFSAUoBUgFKAVIBSgFSAUoBKQElASsBGQHaAR4B2gEeAdoBHgHa
|
||||
AR4B2gEeAdoBHgHbAR4B2wEeAdsBHgG6AR4BugEeAdoBHgG6AR4B2gEeAUwBGQEIASEBUgFKAVIBSgFS
|
||||
AUoBUgFKAVIBSgFSAUoBUgFKAVIBSgFSAUoBUgFKAVIBSgFSAUoBUgFKAVIBSgEpASUBbAEZAT8BIwE/
|
||||
ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBbQEZASkBJQG1
|
||||
AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAUoBKQFs
|
||||
ARkBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwFt
|
||||
ARkBKQElAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1
|
||||
AVYBSgEpAWwBGQE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/
|
||||
ASMBPwEjAW0BGQEpASUBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1
|
||||
AVYBtQFWAbUBVgFKASkBbAEZAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/
|
||||
ASMBPwEjAT8BIwE/ASMBbQEZASkBJQG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1
|
||||
AVYBtQFWAbUBVgG1AVYBtQFWAUoBKQFsARkBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/
|
||||
ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwFtARkBKQElAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1
|
||||
AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBSgEpAWwBGQH/ASYBfwEqAX8BKgF/ASoBfwEqAX8BKgH/
|
||||
ASYB/wEmAX8BKgF/ASoBfwEqAX8BKgF/ASoB/wEmAW0BGQEpASUBlAJSAUoBUgFKAVIBSgFSAUoBUgFK
|
||||
AZQBUgGUAlIBSgFSAUoBUgFKAVIBSgFSAUoBlAFSAUoBKQFsARkBPwEjAT8BIwE/ASMBPwEjAT8BIwE/
|
||||
ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwFtARkBKQElAbUBVgG1AVYBtQFWAbUBVgG1
|
||||
AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBSgEpAWwBGQF/ASoBfwE8AX8BPAF/
|
||||
ATwBfwE8AX8BPAF/ASoBfwEqAX8BPAF/ATwBfwE8AX8BPAF/ATwBfwEqAW0BGQEpASUBUgJKASkBSgEp
|
||||
AUoBKQFKASkBSgEpAVIBSgFSAkoBKQFKASkBSgEpAUoBKQFKASkBUgJKASkBbAEZAT8BIwE/ASMBPwEj
|
||||
AT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBbQEZASkBJQG1AVYBtQFW
|
||||
AbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAUoBKQFsARkBfwEq
|
||||
AX8BPAF/ATwBfwE8AX8BPAF/ATwBfwEqAX8BKgF/ATwBfwE8AX8BPAF/ATwBfwE8AX8BKgFtARkBKQEl
|
||||
AVICSgEpAUoBKQFKASkBSgEpAUoBKQFSAUoBUgJKASkBSgEpAUoBKQFKASkBSgEpAVICSgEpAWwBGQE/
|
||||
ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAW0BGQEp
|
||||
ASUBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgFK
|
||||
ASkBbAEZAX8BKgF/ATwBfwE8AX8BPAF/ATwBfwE8AX8BKgF/ASoBfwE8AX8BPAF/ATwBfwE8AX8BPAF/
|
||||
ASoBbQEZASkBJQFSAkoBKQFKASkBSgEpAUoBKQFKASkBUgFKAVICSgEpAUoBKQFKASkBSgEpAUoBKQFS
|
||||
AkoBKQFsARkBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEj
|
||||
AT8BIwFtARkBKQElAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFW
|
||||
AbUBVgG1AVYBSgEpAWwBGQF/ASoBfwE8AX8BPAF/ATwBfwE8AX8BPAF/ASoBfwEqAX8BPAF/ATwBfwE8
|
||||
AX8BPAF/ATwBfwEqAW0BGQEpASUBUgJKASkBSgEpAUoBKQFKASkBSgEpAVIBSgFSAkoBKQFKASkBSgEp
|
||||
AUoBKQFKASkBUgJKASkBbAEZAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/
|
||||
ASMBPwEjAT8BIwE/ASMBbQEZASkBJQG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1
|
||||
AVYBtQFWAbUBVgG1AVYBtQFWAUoBKQFsARkB/wEmAX8BKgF/ASoBfwEqAX8BKgF/ASoB/wEmAf8BJgF/
|
||||
ASoBfwEqAX8BKgF/ASoBfwEqAf8BJgFtARkBKQElAZQCUgFKAVIBSgFSAUoBUgFKAVIBSgGUAVIBlAJS
|
||||
AUoBUgFKAVIBSgFSAUoBUgFKAZQBUgFKASkBbAEZAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/
|
||||
ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBbQEZASkBJQG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1
|
||||
AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAUoBKQFsARkBPwEjAT8BIwE/ASMBPwEjAT8BIwE/
|
||||
ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwFtARkBKQElAbUBVgG1AVYBtQFWAbUBVgG1
|
||||
AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBSgEpAUwBGQE/ASMBPwEjAT8BIwE/
|
||||
ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAW0BGQEpASUBtQFWAbUBVgG1
|
||||
AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgFKASkBTAEZAT8BIwE/
|
||||
ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBPwEjAT8BIwE/ASMBbQEZASkBJQG1
|
||||
AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAUoBKQHw
|
||||
AT0B6AEYAegBGAHoARgB6AEYAegBGAHoARgB6AEYAegBGAHoARgB6AEYAegBGAHoARgB6AEYAegBGAHv
|
||||
AT0B7wE9AecBHAHnARwB5wEcAecBHAHnARwB5wEcAecBHAHnARwB5wEcAecBHAHnARwB5wEcAecBHAHn
|
||||
ARwB7wE9AfABPQHoARgB6AEYAegBGAHoARgB6AEYAegBGAHoARgB6AEYAegBGAHoARgB6AEYAegBGAHo
|
||||
ARgB6AEYAe8BPQHvAT0B5wEcAecBHAHnARwB5wEcAecBHAHnARwB5wEcAecBHAHnARwB5wEcAecBHAHn
|
||||
ARwB5wEcAecBHAHvAT0BQgFNAT4HAAE+AwABKAMAAUADAAEgAwABAQEAAQEGAAEBFgAD/4EAAfABDwHw
|
||||
AQ8B8AEPAfABDwHwAQ8B8AEPAfABDwHwAQ8B/AE/AfwBPwH8AT8B/AE/aAAL
|
||||
</value>
|
||||
</data>
|
||||
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
|
||||
<value>6, 13</value>
|
||||
<value>8, 16</value>
|
||||
</data>
|
||||
<data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
|
||||
<value>1044, 749</value>
|
||||
<value>1392, 922</value>
|
||||
</data>
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
@@ -957,7 +1097,7 @@
|
||||
</value>
|
||||
</data>
|
||||
<data name="$this.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>2, 2, 2, 2</value>
|
||||
<value>3, 2, 3, 2</value>
|
||||
</data>
|
||||
<data name="$this.StartPosition" type="System.Windows.Forms.FormStartPosition, System.Windows.Forms">
|
||||
<value>CenterScreen</value>
|
||||
@@ -1013,6 +1153,12 @@
|
||||
<data name=">>mainToolTip.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.ToolTip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>displaySelectorImageList.Name" xml:space="preserve">
|
||||
<value>displaySelectorImageList</value>
|
||||
</data>
|
||||
<data name=">>displaySelectorImageList.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.ImageList, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>$this.Name" xml:space="preserve">
|
||||
<value>KVMViewer</value>
|
||||
</data>
|
||||
|
||||
65
KVMViewerExtra.Designer.cs
generated
Normal file
65
KVMViewerExtra.Designer.cs
generated
Normal file
@@ -0,0 +1,65 @@
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MeshCentralRouter
|
||||
{
|
||||
partial class KVMViewerExtra
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(KVMViewerExtra));
|
||||
this.resizeKvmControl = new MeshCentralRouter.KVMResizeControl();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// resizeKvmControl
|
||||
//
|
||||
this.resizeKvmControl.BackColor = System.Drawing.Color.Gray;
|
||||
resources.ApplyResources(this.resizeKvmControl, "resizeKvmControl");
|
||||
this.resizeKvmControl.Name = "resizeKvmControl";
|
||||
this.resizeKvmControl.ZoomToFit = false;
|
||||
this.resizeKvmControl.Enter += new System.EventHandler(this.resizeKvmControl_Enter);
|
||||
this.resizeKvmControl.Leave += new System.EventHandler(this.resizeKvmControl_Leave);
|
||||
//
|
||||
// KVMViewerExtra
|
||||
//
|
||||
resources.ApplyResources(this, "$this");
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.Gray;
|
||||
this.Controls.Add(this.resizeKvmControl);
|
||||
this.Name = "KVMViewerExtra";
|
||||
this.Activated += new System.EventHandler(this.KVMViewer_Activated);
|
||||
this.Deactivate += new System.EventHandler(this.KVMViewer_Deactivate);
|
||||
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.KVMViewerExtra_FormClosed);
|
||||
this.Load += new System.EventHandler(this.MainForm_Load);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
private KVMResizeControl resizeKvmControl;
|
||||
}
|
||||
}
|
||||
|
||||
125
KVMViewerExtra.cs
Normal file
125
KVMViewerExtra.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading;
|
||||
|
||||
namespace MeshCentralRouter
|
||||
{
|
||||
public partial class KVMViewerExtra : Form
|
||||
{
|
||||
private MainForm parent = null;
|
||||
private KVMViewer mainViewer = null;
|
||||
private KVMControl kvmControl = null;
|
||||
public KVMControl mainKvmControl = null;
|
||||
private int displayId;
|
||||
public string lang = Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName;
|
||||
|
||||
public KVMViewerExtra(MainForm parent, KVMViewer mainViewer, NodeClass node, KVMControl mainKvmControl, int displayId)
|
||||
{
|
||||
this.parent = parent;
|
||||
this.mainViewer = mainViewer;
|
||||
this.mainKvmControl = mainKvmControl;
|
||||
this.displayId = displayId;
|
||||
InitializeComponent();
|
||||
Translate.TranslateControl(this);
|
||||
this.Text += " - " + node.name + " (" + displayId + ")";
|
||||
kvmControl = resizeKvmControl.KVM;
|
||||
kvmControl.desktop = mainKvmControl.desktop;
|
||||
kvmControl.parentEx = this;
|
||||
//kvmControl.Visible = true;
|
||||
kvmControl.DesktopSizeChanged += KvmControl_DesktopSizeChanged;
|
||||
kvmControl.cropDisplay(mainKvmControl.displayOrigin, mainKvmControl.displayInfo[displayId]);
|
||||
resizeKvmControl.ZoomToFit = true;
|
||||
this.MouseWheel += MainForm_MouseWheel;
|
||||
}
|
||||
|
||||
public void UpdateScreenArea(Bitmap desktop, Rectangle r)
|
||||
{
|
||||
if (kvmControl.displayCrop.IntersectsWith(r) == false) return;
|
||||
Rectangle r2 = new Rectangle(r.X, r.Y, r.Width, r.Height);
|
||||
r2.Intersect(kvmControl.displayCrop);
|
||||
kvmControl.desktop = desktop;
|
||||
if (kvmControl.ScaleFactor == 1)
|
||||
{
|
||||
Rectangle r3 = new Rectangle(r2.X - kvmControl.displayCrop.X, r2.Y - kvmControl.displayCrop.Y, r2.Width, r2.Height);
|
||||
kvmControl.Repaint(r3);
|
||||
}
|
||||
else
|
||||
{
|
||||
Rectangle r3 = new Rectangle((int)(((double)(r2.X - kvmControl.displayCrop.X)) / kvmControl.ScaleFactor) - 2, (int)(((double)(r2.Y - kvmControl.displayCrop.Y)) / kvmControl.ScaleFactor) - 2, (int)(((double)r2.Width) / kvmControl.ScaleFactor) + 4, (int)(((double)r2.Height) / kvmControl.ScaleFactor) + 4);
|
||||
kvmControl.Repaint(r3);
|
||||
}
|
||||
}
|
||||
|
||||
private void KvmControl_DesktopSizeChanged(object sender, EventArgs e)
|
||||
{
|
||||
//kvmControl.Visible = true;
|
||||
}
|
||||
|
||||
void MainForm_MouseWheel(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.Delta == 0) return;
|
||||
Control c = this.GetChildAtPoint(e.Location);
|
||||
if (c != null && c == resizeKvmControl) resizeKvmControl.MouseWheelEx(sender, e);
|
||||
}
|
||||
|
||||
private void MainForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
this.Size = new Size(820, 480);
|
||||
resizeKvmControl.CenterKvmControl(false);
|
||||
kvmControl.Repaint(null);
|
||||
}
|
||||
|
||||
public void OnScreenChanged()
|
||||
{
|
||||
resizeKvmControl.CenterKvmControl(true);
|
||||
}
|
||||
|
||||
private void resizeKvmControl_Enter(object sender, EventArgs e)
|
||||
{
|
||||
kvmControl.AttachKeyboard();
|
||||
}
|
||||
|
||||
private void resizeKvmControl_Leave(object sender, EventArgs e)
|
||||
{
|
||||
kvmControl.DetacheKeyboard();
|
||||
}
|
||||
|
||||
private void KVMViewer_Deactivate(object sender, EventArgs e)
|
||||
{
|
||||
kvmControl.DetacheKeyboard();
|
||||
}
|
||||
|
||||
private void KVMViewer_Activated(object sender, EventArgs e)
|
||||
{
|
||||
kvmControl.AttachKeyboard();
|
||||
}
|
||||
|
||||
bool isPointVisibleOnAScreen(Point p)
|
||||
{
|
||||
foreach (Screen s in Screen.AllScreens) { if ((p.X < s.Bounds.Right) && (p.X > s.Bounds.Left) && (p.Y > s.Bounds.Top) && (p.Y < s.Bounds.Bottom)) return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
private void KVMViewerExtra_FormClosed(object sender, FormClosedEventArgs e)
|
||||
{
|
||||
mainViewer.extraScreenClosed();
|
||||
}
|
||||
}
|
||||
}
|
||||
599
KVMViewerExtra.resx
Normal file
599
KVMViewerExtra.resx
Normal file
@@ -0,0 +1,599 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="resizeKvmControl.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
|
||||
<value>Fill</value>
|
||||
</data>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="resizeKvmControl.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>0, 0</value>
|
||||
</data>
|
||||
<data name="resizeKvmControl.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>4, 4, 4, 4</value>
|
||||
</data>
|
||||
<data name="resizeKvmControl.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>826, 522</value>
|
||||
</data>
|
||||
<assembly alias="mscorlib" name="mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="resizeKvmControl.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>10</value>
|
||||
</data>
|
||||
<data name=">>resizeKvmControl.Name" xml:space="preserve">
|
||||
<value>resizeKvmControl</value>
|
||||
</data>
|
||||
<data name=">>resizeKvmControl.Type" xml:space="preserve">
|
||||
<value>MeshCentralRouter.KVMResizeControl, MeshCentralRouter, Version=1.8.8062.29471, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
<data name=">>resizeKvmControl.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>resizeKvmControl.ZOrder" xml:space="preserve">
|
||||
<value>0</value>
|
||||
</data>
|
||||
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
|
||||
<value>8, 16</value>
|
||||
</data>
|
||||
<data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
|
||||
<value>826, 522</value>
|
||||
</data>
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
AAABAAkAEBAQAAEABAAoAQAAlgAAABAQAAABAAgAaAUAAL4BAAAgIBAAAQAEAOgCAAAmBwAAICAAAAEA
|
||||
CACoCAAADgoAADAwEAABAAQAaAYAALYSAAAwMAAAAQAIAKgOAAAeGQAAEBAAAAEAIABoBAAAxicAACAg
|
||||
AAABACAAqBAAAC4sAAAwMAAAAQAgAKglAADWPAAAKAAAABAAAAAgAAAAAQAEAAAAAACAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA/wAA/wAAAP//AP8A
|
||||
AAD/AP8A//8AAP///wAACIiHh4eAAAAPiIh4eAAAAAAIh3eAAACIiIiIiIh4eI+IiIiIiIiIiEREREZE
|
||||
Z4iIRGRMfIyMiIhlxMTIeMeIiFZEbHjIjoiIbExMiIiHiIhWxsyIiIiIiExMx4iIiIiITGzIj4+IiIhM
|
||||
TM6I6OiIiHiIiIeIiIgI+IiIiIiIiOAHAADgDwAA+B8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAoAAAAEAAAACAAAAABAAgAAAAAAAABAAAAAAAAAAAAAAAB
|
||||
AAAAAQAAAAAAAIAAAACGCwkAlAAAAJQNAgCfEQAAnBsQAJgdEQCiDgAAqQ0AAKgSAACqFQAApxkNAKUc
|
||||
DwCyEgAAsRUAALQXAAC/FgIAuBgAAL0YAACaJhwArCcVAKMnHQC7Mh8AmDAoAJ42LACqMCMApTctAKU+
|
||||
MwDAGwAAwRwAAMUdAADKGgAAyh4FANIbAADdGQAA4RoAAOcaAADRIQAA1SMAAPEnCQDkMxMAvkwqALpI
|
||||
OADMSjYA81A1AKVIQACtSkEAr1ZMAM5dTADUXUgA1GZKANhgSwDdYUwA3WpXAON5ZgDgfWsA6HxoAPp9
|
||||
aADmgWgA7IBrAPiKawDqi3oA8JtyAPahdwD6qH8AiYuLAIyOjgCXmpoAmp2dAJ6fnwCeoaEAoKGhAKOj
|
||||
pACipKQApKamAKaoqQCoqqoAqaytAKyurwCvsbEAsbS1ALO3uAC1uLkAtru8ALm+vgDvk4IA7ZuNAPOX
|
||||
hQDzn4oA9ZyLAPuuiQD3qpsA+q6eAPu0kQD0saYA+7KjAPi1oAD+sqQA+7+iAP7DswD6xrQA/8a2AP7G
|
||||
ugD/yboA+s2+ALzBwQC+xMQAvsvNAL/MzQDFyMkAwczNAMnMzADDztAAxM7QAMbQ0QDJ0dIAytLUAMzT
|
||||
1QDN1NUA1NbXANjY2ADc3NwA/9LGAP/UxgD/1cgA/9rLAP/i2QD/5twA/+nfAN7h4QDo6OgA/+rgAP/r
|
||||
5gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA////AAAAAFVVUk1GRkZGRkYAAAAAAACDeXduU0tGTUYAAAAAAAAAAAB5T0RDQ24AAAAAAIJr
|
||||
a1VVU1JPT09NTEtLRm53d3J0cnNuc3JucW1tbW1Ld08BAQIBAQMVFRUVFSttS3dNBxQHBAUKFzEyNDUq
|
||||
bUt3TRgYBwoKDyw4Nzk8NG1Ld0wuHAcPDxE2V1ZYWjtuTXdLMBsIDxIhPl9cXWJZc013Sy8WDxIiKWJn
|
||||
ZGRoX21Pd0saCR0nJC17fXt+fmVtT3dGDRAdJyU6hX9/hIRoc093SwwRISMoPWNeW0FAP3NSd0ZGRktL
|
||||
S01PT09SUlNzUgB3d3d3d3d3d3d3c3dzcnjgBwAA4A8AAPgfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAKAAAACAAAABAAAAAAQAEAAAAAAAAAgAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA/wAA/wAAAP//AP8A
|
||||
AAD/AP8A//8AAP///wAAAAAAAAAAj4AAAAAAAAAAAAAAAAAIj4iIiAAAAAAAAAAAAAAIj4+Pj4iIAAAA
|
||||
AAAAAAAAiIj4+I+IiIcAAAAAAAAACIiIj4iIiIh4cAAAAAAAAAiIiPiPiIiHeAAAAAAAAAAIiIiIiIiH
|
||||
d4cAAAAAAAAAAAiIiId3d3eIiIAAAAAAAAAAh3d3d3eIiIiAAAAAAAAAAACHd3iIiIiIgAAAAAAAAIeH
|
||||
iIiIh8fEeHAAAAAId4iIiId3xExETH+AAAAAeIiId3RExExsbGx4gAAAD3d3RERERExnx8fHz3AAAACE
|
||||
RERETExEx8fIx8+IAAAAhERkTERGxnyMjI54iAAAAIR8VkRGxEyMjnjIyIgAAACHRkxExEzGh3fIjIiI
|
||||
AAAAh0d8RkxsTIeIh4joiAAAAIfHx0xExMiHd46HiIgAAACIR3xExsbHiI6IiHiHAAAAiEjERMTMyI6I
|
||||
iIiIiAAAAAhHxMbGzGiIiIiIiIiAAAAIbEZMzGzPiIiIiIiIgAAACFZMTGzMj4+Pj4+IiIAAAAhsTGxM
|
||||
bIj4+Pj/+PiAAAAIVETEzMz/+P+Pj4iIgAAACHTGzGzOiIiIiIiIj3AAAAiETEzGx4iIiIiI+PgAAAAI
|
||||
hHd3iIiIj4//AAAAAAAACIiIj4+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/8f///4A///4AD//8A
|
||||
AP/+AAB//gAA//4AAP//gAAf/8AAH//wAB//AAAf4AAAH8AAAB+AAAAfwAAAD8AAAA/AAAAPwAAAD8AA
|
||||
AA/AAAAPwAAAD8AAAA/gAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAP4AAD/+AH////////KAAAACAA
|
||||
AABAAAAAAQAIAAAAAAAABAAAAAAAAAAAAAAAAQAAAAEAAAAAAAB+AQAAZmdmAGlpagB2dnYAfX1+AIIA
|
||||
AACMAgAAhQsCAIwMAQCSAAAAmAcAAJMLAQCbDgAAkwwIAIsUCgCUEgUAnRAAAJIYDACLHBQAkB4WAJoe
|
||||
EgCmAAAAqgYAAKELAAC5CAAApBIAAKsUAACqGAYArBwJALIVAAC5EwAAsxgBALsZAACNJBwAkyQcAKYg
|
||||
DwC2IA0AoCATAKwjEQCgJxoAsy0bALcxHgCSJiAAliskAJYvKACfMCUAmjIqAI85NACZNjAAmz01AJc+
|
||||
OAC0MiEAvDUhAL0/LQDFEwAAwhsAAMsdAADQHAAA2BwAAO8UAADkGwAA6x0AANMgAADbIgAA2iQMAMAs
|
||||
FQDlIQAA5S4LAPIqAwDhLhgA9j8dAMs8JQDOPygAmUQ8AKhANgCgQTkAr0U6AMNCLwDDRTIAyUYyAMxI
|
||||
MwDBTD8AzVI/ANZROQDaVj8A8UQiAP5UMgCZU00Al1RRAKRKRACuVUwAsVJHALBUSgCiWlUArFhRALFc
|
||||
VQCzZF0AmmtqALFvZgC5a2QAr3FtALdwawC+dWsAoHVyALZ4cQDHU0IAzF1MANFWQQDVWUQA2FpFANVe
|
||||
SAD1X0IAxGlaANVlUgDcZlIA3WhUANhuXQDiY0kA4mZQAOJqVADpcFoAxnRoAN10YgDjd2QA5nllAOp8
|
||||
ZgDyfGYA6IBtAPqFbgDjhHQA6YZ0AOyIdgDuingA8Y16APqNeQCDhIQAi4yOAIuOkgCOlZoAlZWVAJSV
|
||||
mACWm5wAnZ2dAKGFhQCzhIEAp5KSAKCfnwCqnZ4AspOTAL2VkwC5nJsAuaGcAJeepACVoaYAnKCmAJit
|
||||
qgCfrrEAoqKiAKukpwCmpqgApqmrAKurqwCyp6kAsKqsAKyssAClsLMArbKzAKS6tgCttbkAs7O0ALW5
|
||||
vAC6ursA0ZWSAO2WhgDrmIoA8piHAPWbigD7nowAy6KcAOKqnADtrJ0A8qOVAPikkwDwqZ0A/KubAPG1
|
||||
ngD/sJ0A9bieAMCtrADbtKoAwre0AMq1sQDFuLYAwbu9ANG1sADbuLMA4K6jAOu8pwDgtKgA57+tAPWw
|
||||
ogD7tKUA+b+mAPS3qwD+vK0A/r+xANXCvgD1wKoA+8euAOjGuAD+xLIA/sm1AP7EuQD9y7sAvb/DAMG/
|
||||
wQC3wcQAvMLDALnGyAC+y8wAw8PDAMTFyADDyswAy8vLANXKxgDSzcsA2M/LAMLP0ADMz9AAx9XWAMzT
|
||||
1ADK1tgA09PTANLW2ADU2twA29zcAOzPwgD/zsEA/9LDAP/VyQD/2coA5NvXAOvc1gDs3tgA/93SAP/h
|
||||
1AD/5NoA/+neANvf4ADe4OIA4+TkAObp6gD/6+QA//HrAP///wAAAAAAAAAAAAAAAAAAAOzs5QAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAA6enp6erl5d2sAAAAAAAAAAAAAAAAAAAAAAAAAAAA3enp7Oz66uXy
|
||||
7NjdrAAAAAAAAAAAAAAAAAAAAAAAAN3g4Onp7Prj4OzgrOCqrIwAAAAAAAAAAAAAAAAAAACs3d3d4Or6
|
||||
+ung6d3dqqKTp4wAAAAAAAAAAAAAAAAAAKqsrN3d6enp4N3drKqgjIyiAAAAAAAAAAAAAAAAAAAA7Kzd
|
||||
rN3d4ODdrKqTiIiJk48AAAAAAAAAAAAAAAAAAAAAAKTYqqSioIyIBAIDiKCqqqysqgAAAAAAAAAAAAAA
|
||||
AAAAAKCMoIyIBAWIjaKn2dzm5sKiAAAAAAAAAAAAAAAAAAAAAACgiYmKi6fb5OXgw63A3qAAAAAAAAAA
|
||||
AAAAAAAAoqCbmZmdp9nCwbN6UikeFmnmkwAAAAAAAAAAoo6LoavZ29msvZZmTSccGhsbHScgZ+igAAAA
|
||||
AAAAAIqcqNmswpdlWisMBwoKJCk0NCoqNUJx5qAAAAAAAAD6oJWRXisGBgEGBwwNERs0NjZOUFBRSWvm
|
||||
ogAAAAAAAACfAQYJCAgICAkMEREbHE9qU2xsbm5Vb+Wq4AAAAAAAAKUTEyMTEw8JDBERHBsla3Jyc3R4
|
||||
eHh34dmsAAAAAAAAqjAjLSsjEgwRERsbHkJ1e3t8fX1+fnnP2aQAAAAAAACrWSMyMS4MDBocGx4fSIKC
|
||||
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
|
||||
AADTHQAA5RoAAMYjCADYIQAAzzAVAOckAADwKAIA9TEKAO85FgD0OBIAwTciAMI5JADBPisAyT4oANY8
|
||||
IgClQzsAvUQ0ALdKNwDFQS0AykQvANBDLADCRjQAykUwAMRINgDKSjYAwko6AM5NOADXTjYA0VA8APRK
|
||||
KACNSUEAk0pFAJtTTgCXWFQApktEAKpRSgCzUEUAuVBCALFWTAC4VEoArVdQAKtYUgCmXVgAtF1TALBf
|
||||
WgCbY14At2BUAJVlYQCcfHkAomZhALhrYwC7c2wAoHRzAL54cAC2f3sAylVDANVaRgDiWkIA12JOANlo
|
||||
VQDpZUwA+GFDAORrVQDncl0AxHVqAM56bgDRcGIA3XRiAN57awDBfHUA5XpnAPt+ZQCugXsA3oFvAMWF
|
||||
fADYinwA5oBuAPOBawDqiHYA9Yp1APaRfQCCgoMAioqMAJ2EgwCIkI4AgJ2MAIyNkQCOkZUAjJOYAJKS
|
||||
lACWlpkAmpqbAKSKigC0iIUAs42LALGSjgCmmJgAh6SYAJ2eogCaoaYAnaWpAJ+trACjo6MApKaqAKim
|
||||
qACjqawAq6urALWpqQCurrAArLK1AK+4uwC0tLQAurO0ALW2uAC8t7gAtby/ALu7uwDOkIUAyZaPAMSf
|
||||
nADan5QA6peHAPWZhwDtn5EA8Z+QAMWhmgDaqpgA+qWNAOeolQD3qJgA97SaAMGlpADDrKsAyK2qAMqx
|
||||
rgDRsacA2LOjANSyrgDatKwAw7W0AMa4twDHvLwAyb28ANu7tADUvbgA5a+jAPOvogDks6gA+7enAOjA
|
||||
rgD8wqoA5ci8AP7HtwD/0b0Atr7BALi+wQC7wsMAv8rNAMLCwgDJxsUAxMXIAMPKzADLy8sA1MfGANTJ
|
||||
xgDaysUA3c/JANnSzwDOz9AAxdDTAMzT1ADO19gA09PTANrV1ADR19gA1dnaANrb2wDlzcMA/87DAP/W
|
||||
xwDi1tEA/93TAObh3wD/5NoA3N7gANvg4QDj4+MA6errAP/q4gDu8vQA8fP0AAAAAAD///8AAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAA6+vr4d0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOHh
|
||||
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
|
||||
z/+qrKz/zdTW/6Gjo/+qMCP/qQ0A/8AbAP/RIQD/4RoA//NQNf//0sb//9TI///Uxv//18j//9rL//rG
|
||||
tP/Dzs//rK6v/87U1v+goaH/pRwP/7MWAP/FHQD/1SMA/+caAP/6fWj//+vm///i2f//5tz//+nf///q
|
||||
4P/6zb7/xM7Q/6+ysv/O1Nb/oKGh/6cZDf+4GAD/yhoA/90ZAP/xJwn/+Ipr//u/ov/7tJH/+66J//qo
|
||||
f//2oXf/8Jty/8XO0P+xtLX/ztTW/6Chof+goaH/oKGh/6Gio/+jpaX/paen/6epqf+prKz/rK+v/6+x
|
||||
sf+xtLX/tLi4/7a7vP/Fz9H/s7e4/87U1njO1Nb/ztTW/87U1v/N1Nb/zdPV/83T1f/M09X/y9LU/8rS
|
||||
1P/K0tP/ydHT/8jR0v/H0NH/xs/R/7a6u5XgBwAA4AcAAPAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAACAAAABAAAAAAQAgAAAAAACAEAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACjo6MDurq6I7S0
|
||||
tFatra18t7e3hbm5uYeoqKiGjo6Of4KCgmB7e3stg4ODCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkJCQHbCw
|
||||
sHzHx8fIzs7O8NXV1fvZ2dn+1tbW/s7Ozv7MzMz8wsLC9Kurq9WUlJRrjo6OMAAAAAAAAAAAAAAAAAAA
|
||||
AAEAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJWV
|
||||
lWu+vr7r0tLS/9fX1//b29v/3t7e/9zc3P/U1NT/zc3N/93d3f/b29v/wcHB/8XFxf+4uLj+eXl5UBMT
|
||||
ExMAAAAMAAAAGgAAABQAAAAHAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
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
|
||||
AAIAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBgYEJj4+Pdr29verQ0ND/1tbW/9ra2v/b29v/3Nzc/9vb
|
||||
2//Z2dn/1tbW/9HR0f/Ly8v/zs7O/9ra2v/a2tr/ysrK/8HBwf+9vb3/t7e3/5ubm7g1NTU6AAAAAAAA
|
||||
AAIAAAAJAAAADQAAAA8AAAAOAAAACQAAAAMAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIiCyqqqrOzc3N/83Nzf/Ly8v/z8/P/9PT
|
||||
0//X19f/2tra/9vb2//a2tr/19fX/9LS0v/MzMz/0dHR/9/f3//Z2dn/wMDA/7e3t/++vr7/ycnJ/7i4
|
||||
uP+wsLD9WVlZiAAAABYAAAAjAAAAKwAAACsAAAAlAAAAGQAAAA0AAAAGAAAAAwAAAAEAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi4uLJbS0tOfIyMj/w8PD/8bG
|
||||
xv/Ly8v/zs7O/9LS0v/X19f/29vb/9zc3P/c3Nz/2NjY/9HR0f/Kysr/09PT/+Hh4f/Q0ND/ubm5/8DA
|
||||
wP/Pz8//urq6/62trf+urq7/ubm5/2FhYawAAABDAAAARgAAAEAAAAA2AAAAKQAAABwAAAARAAAACQAA
|
||||
AAQAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJiYkDq6urvcDA
|
||||
wP++vr7/wsLC/8TExP/IyMj/zMzM/9HR0f/X19f/29vb/93d3f/c3Nz/2NjY/9HR0f/Jycn/0tLS/9vb
|
||||
2//FxcX/wcHB/8nJyf+6urr/sLCw/66urv+oqKj/oqKi/6qqqv8fHx93AAAATgAAAEkAAAA+AAAAMwAA
|
||||
ACYAAAAbAAAAEQAAAAoAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAChoaEXtra29Lm5uf+8vLz/v7+//8LCwv/FxcX/ycnJ/87Ozv/U1NT/2dnZ/9zc3P/b29v/1tbW/87O
|
||||
zv/Hx8f/zMzM/8zMzP/AwMD/w8PD/7e3t/+ysrL/rq6u/6SkpP+ampr/l5eX/6qqqv9GRkaXAAAARwAA
|
||||
AEgAAABAAAAANQAAACgAAAAfAAAAFgAAAA4AAAAHAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAC6uroWtLS08be3t/+5ubn/vLy8/7+/v//BwcH/xcXF/8nJyf/Pz8//1NTU/9bW
|
||||
1v/V1dX/0dHR/8rKyv/ExMT/xcXF/8DAwP++vr7/t7e3/7Gxsf+pqan/n5+f/5WVlf+SkpL/mJiY/6ur
|
||||
q/9RUVGcAAAAPAAAAEEAAAA6AAAAMQAAACcAAAAeAAAAFgAAAA4AAAAHAAAAAwAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0tLQCtbW1y7W1tf+3t7f/ubm5/729vf+/v7//wcHB/8TE
|
||||
xP/Hx8f/y8vL/83Nzf/MzMz/ycnJ/8XFxf/BwcH/v7+//7q6uv+ysrL/qamp/6Ghof+Xl5f/kpKS/5OT
|
||||
k/+YmJj/nZ2d/6urq/8pKSltAAAALgAAADQAAAAzAAAALAAAACMAAAAaAAAAEwAAAAwAAAAHAAAAAgAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqampQrOzs/e7u7v/t7e3/7q6
|
||||
uv+8vLz/vr6+/8DAwP/CwsL/xMTE/8bGxv/FxcX/wsLC/7y8vP+1tbX/ra2t/6ampv+bm5v/jIyM/3t7
|
||||
e/95eXn/ioqK/5SUlP+bm5v/pqam/4GBgcoWFhZFODk5YTk5Olpubm5aEhISKQAAABwAAAAWAAAADgAA
|
||||
AAgAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGdn
|
||||
Z0WZmZnNu7u7/7a2tv+zs7P/tLS0/7S0tP+zs7P/srKy/7CwsP+tra3/pqam/5ubm/+SkpL/iIiI/3x8
|
||||
fP9qamn/X19f/2VlZf97e3z/jY6O/56en/+sra3/tre3/pubnM6urq/iycrK/7a2t+6IiIi+Z2dnKwAA
|
||||
ABEAAAALAAAABwAAAAMAAAACAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAICAgGTk5ObJ2dneiurq7/qamp/6Ojo/+enp7/m5ub/5ycnP+Pj4//goGB/3p6
|
||||
ev9zc3P/bm5u/2tsbP91dnf/hIWG/5iYmv+goaL/sLCx/7e3uP+3t7f/u7u7/8HBwf/AwMD/v7+//L6+
|
||||
vv+Xl5ftgICAMQAAAAMAAAADAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAABAAAAAwAAAAYAAAAGAAAAABAQECNGRkZ0eXl5v4+PjuKgoKD4o6Oj/ouL
|
||||
iv97e3v/gICB/4SEhf+IiYv/kJCT/5manP+oqKv/rq6w/66ur/+vr7D/r6+w/7a3t/+1t7f/u8LD/8LM
|
||||
zf/Jzs//wcDA/by8vPyfn5/6b29vUwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAAGAAAACQAAAAwAAAAOAAAADQAAAAUAAAAAFhYXC0BA
|
||||
QjBvb3GBjo+R7oqKjf+OjpL/kJCU/4+QlP+Skpb/lpaZ/56eof+lpaf/p6mr/6yxtP+1vsD/wMnL/87T
|
||||
1P/W09P/2cnG/9+4tP/Wvrn/wMXF/cHBwfyioqL8jIyMbgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQEARQUFQgtLS8XSkpMNWpq
|
||||
bGaCgoaYj4+TxJSUmOWQkJT4jY2R/42Nkf+MjJH/i42R/4uOk/+Nkpf/nKSo/6+4u//Dycv/z87P/9TH
|
||||
xv/Usq7/2p+U/9FwYv/HQS7/wBwE/7QGAP+zX1X/w87P/sTExPyhoaH+n5+fiwAAAAAAAAAAAAAAAAAA
|
||||
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
|
||||
XP/lcl3/5nNe/+Z1YP/nZ1D/24l6/9DX2P/Q0ND/oaGh/pubm3oAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAMrKy5i1vL//kElF/44ZEf+ZMiv/ly4n/5YrJP+UKCH/kiYe/5QmG/+SFgr/kAwA/5UP
|
||||
AP+aDwD/nxEA/6QTAP+oFAD/qxUA/68VAP+zFgD/uBgA/8lDL//Yb17/23Ni/910Yv/fdWP/4ndk/+V4
|
||||
Zf/leWX/53pm/+h8Z//pfWj/6n1p/+t/a//tdV7/3oFv/9DV1v/S0tL/paWl/5ubm5oAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAANXV13m2vsL/m2Fe/44ZEf+dOzP/mzYv/5kzLP+YMCn/mTAn/5oq
|
||||
H/+SEAP/kw4A/5kPAP+eEQD/pBMA/6cUAP+qFQD/rxUA/7QXAP+4GAD/vRsB/9BRPf/ee2v/4H5t/+J+
|
||||
bf/lgG7/6IFu/+iCcP/qg3H/64Rx/+2Fcv/uh3P/74h0//CKdv/ygm3/5Hxo/9LR0f/T1NT/pqam/5qa
|
||||
mr4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODg4VG4v8L/oHRz/44aEv+iRDz/nz84/549
|
||||
Nv+dOzP/ojwy/5ojF/+RDAD/lw8A/54QAP+kEgD/qBQA/6oVAP+vFQD/tRcA/7kZAP++GQD/xCAF/9hj
|
||||
T//kiXr/5ol5/+iKef/qjHv/7I17/+2OfP/vj33/8JB+//KRf//zkoD/9JOB//WVgv/3kX7/7H1n/9TI
|
||||
xv/W2dn/ra2t/5mZmdwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOfn5zO5vsH+noSE/4wc
|
||||
Ff+mS0T/pEhB/6JGP/+kRj7/pkA2/5UWCP+VDQD/mw8A/6ISAP+nFAD/qhUA/64VAP+0FwD/uRkA/74a
|
||||
AP/DGgD/yScM/+B0Yv/plYb/65SF/+yVhf/ulob/8JeH//GZiP/zmYj/9JqJ//abiv/2nIv/952M//ie
|
||||
jf/5noz/84Jr/9W8uP/Y3N3/t7e3/5mZmeoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO7u
|
||||
7xe9wMLwqJyd/4ojHP+pUEn/qFFK/6dOR/+sUUj/pDYs/5MOAP+ZDwD/nxEA/6YTAP+pFAD/rBUA/7IW
|
||||
AP+4GAD/vhoA/8McAP/GGwD/zzAV/+aFdP/tn5H/7p2P//Cej//xn5D/86GR//Whkf/2o5L/96ST//il
|
||||
lP/5ppX/+qaW//unl//8p5f/+4t0/9q0rP/Y3uD/vr6+/5mZmfSenp4HAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAPLy8ge/wMLbs7Gz/4ovKP+qUUv/q1hS/61YT/+wV07/nCQX/5UMAP+cEAD/ohIA/6gU
|
||||
AP+rFQD/sBYA/7YYAP+7GQD/whsA/8YcAP/KGwD/1jwi/+uVhv/wp5v/8aaY//Onmf/1qJr/9qma//iq
|
||||
m//5q5z/+ayc//utnv/8rp7//a+f//6woP//sKD//5aA/+SzqP/Y4OH/w8PD/5mZmfucnJwiAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADGxsi/vMDC/48+Of+qUEr/sF9a/7NhWf+xVUv/lhQG/5kN
|
||||
AP+gEQD/pRMA/6kVAP+uFQD/tBcA/7kYAP+/GgD/xBwA/8gdAP/NHQD/3Ewz/++jlv/yr6P/86+i//Wv
|
||||
ov/3sKP/+LGk//mypP/7s6X//LSm//62pv//tqf//7ao//+4qf//uar//6KN/+Wvo//a4eL/yMjI/5mZ
|
||||
mf6bm5tJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADNzs+bw8jL/5hNSP+oTkj/tmpi/7lr
|
||||
Y/+rRDr/lgwA/50QAP+jEgD/pxQA/6sVAP+xFgD/txgA/78aAP/GHQD/zB4A/9MfAP/aIwL/6WVM//e0
|
||||
p//5ua3/+7mr//y6rP/9u63//b2u//6+rv/+v6///8Gw///CsP//w7H//8Sy///Esv//xrT//7Sc/+iv
|
||||
nP/b4OL/zc3N/5qamv+bm5tzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADW1th3w8nM/5tT
|
||||
Tv+oTET/u3Ns/7tsZP+eKBv/mAsA/6ERAP+oFAD/rhUA/7cYAP+/GwD/xx0A/88fAP/XIQD/3iIA/+Qj
|
||||
AP/sLgn/9oFq//3Btf//wrX//8K1///Etv//xbb//8e3///IuP//ybj//8m5///Luv//zLv//827///O
|
||||
vP//0L3//8Oq/+yulf/c3t//0dHR/5ubm/+ampqcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AADc3N5TxMvN/5dYVP+mR0D/wXx1/7ZbUv+aEgT/oxEA/6oUAP+xFgD/uRkA/8EbAP/HHQD/zR4A/9Qg
|
||||
AP/aIgD/4CMA/+cjAP/vORb/+ZmF//7Jvv//yL3//8m9///Kvf//zL7//82////Ov///z8D//9DA///R
|
||||
wf//0sH//9PC///Uw///1cT//8y2//Guk//b2tn/2NnZ/56env+ampq6AAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAADh4eI4xs3P/5dlYv+lQjn/xoF5/6s9Mf+eDAD/qBQA/6wVAP+0FwD/uxkA/8Ib
|
||||
AP/JHQD/0B8A/9YhAP/cIwD/5CQA/+sjAP/ySyn//K6f///Pxv//zsP//8/E///QxP//0sX//9PF///U
|
||||
xv//1cb//9bH///Xx///2Mj//9jJ///Zyv//28z//9XD//Wxlv/b09D/3+Dh/6Ghof+ZmZnTAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADU1NYbyc/R85x8ef+iPTP/wnZt/6AeD/+hDwD/qRQA/68V
|
||||
AP+3GAD/vhoA/8QcAP/LHgD/0yAA/9ghAP/fIwD/6CQA/+0lAP/2YUP//8K2///VzP//1Mr//9XK///W
|
||||
yv//18v//9jL///ZzP//2sz//9vN///czv//3c///93Q///f0f//4NP//93O//q5nv/dz8n/4+bn/6mp
|
||||
qf+ZmZnkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADt7e4Jys3Q3qmZmP+cOS//s1BF/5sO
|
||||
AP+kEgD/qxUA/7EWAP+5GQD/vxsA/8cdAP/OHgD/1SAA/9siAP/jJAD/6yUA//ArBP/6fmX//9LI///a
|
||||
0f//2dD//9rQ///b0f//3NH//93S///e0v//39L//+DT///h1f//4tb//+PX///k2P//5dn//+LW//3C
|
||||
qf/lz8b/6Ozu/7Ozs/+YmJjynp6eBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzM7QuLq0
|
||||
tf+SKB7/nhsN/50PAP+mEwD/rBUA/7QXAP+8GQD/wRsA/8kdAP/RHwD/1yEA/90jAP/mJQD/7SQA//Q4
|
||||
Ev/+oI3//97X///e1///39b//9/X///g1///4df//+LY///j2P//5Nn//+Xa///m2///593//+fe///o
|
||||
3v//6d///+je///Mtv/mzMH/7fHz/8HBwf+Xl5f6nJycJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAwMHDlcPExf+NIxn/lwkA/6ARAP+nFAD/rhUA/7YXAP+9GgD/wxwA/8sdAP/TIAD/2SIA/98j
|
||||
AP/oJQD/7iUA//dKJ///uq3//+Pd///i2///49v//+Pb///j2///5dz//+bc///n3P//597//+je///p
|
||||
4P//6uH//+vi///r4///7OT//+zk///Uwv/lyLz/7/P1/8zMzP+YmJj+nJycSQAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAy8vNdsLJyv+KMSj/mQgA/6ERAP+oFAD/rxYA/7gYAP++GgD/xBwA/80e
|
||||
AP/VIAD/2yIA/+EkAP/pJQD/8CUA//piQ///z8X//+fh///l3///5t///+bf///n4P//6OD//+nh///q
|
||||
4f//6+L//+vj///s5P//7OT//+3l///s5P//7OT//+rg///Uv//owK7/8fX3/9bW1v+YmJj/m5ubawAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArq6xVcjR0/+NSUH/mQYA/6MSAP+pFAD/sBYA/7kY
|
||||
AP+/GwD/xhwA/84eAP/WIQD/3CIA/+MkAP/rJQD/8ioC//x+Zf//39j//+rl///p5P//6uT//+rk///q
|
||||
4///6uH//+nf///m3P//5Nj//+HU///czP//18T//9G8//3JtP/5w6v/9ryk//Gtjv/WppL/7/P1/+Xl
|
||||
5f+YmJj/np6ejAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0tLUNsXNz/6UZWD/lwUA/6QS
|
||||
AP+pFAD/sRYA/7oZAP/AGwD/xh0A/9AfAP/WIQD/3SIA/+QkAP/sJAD/9TEK//+TfP//39f//9/W///X
|
||||
y///0MH//8m4//3DsP/3vqn/9Lqk//S5of/0tp3/9LOY/+mulv/frpr/2LOj/9i+tP/cy8T/4tbR/+bh
|
||||
3//m5ub/8fHx/+jo6P+mpqb6s7OzTQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAubm7F8HG
|
||||
yO+dhIL/lAcA/6USAP+qFAD/sxYA/7wZAP/DGgD/yhsA/9UaAP/bGgD/4BoA/+YaAP/rGwD/7CsE/+1s
|
||||
Uv/qmYf/4pyM/+GgkP/hpZX/2qqd/9Gxp//Rvrn/1MrH/9nSz//c19b/2dfX/9jZ2v/X29z/297f/9zf
|
||||
4Pvb3d3u2tvc39XW1tnb29vG3Nzcst7e3o3MzMxLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAw8PGBby/wdeomZn/lQcA/6YJAP+oCwD/rw0A/7URAP+1GAD/tSIL/7c1IP+3Sjf/vGBQ/8Z1
|
||||
aP/Fin//wKCa/8W3tP/LxsX/zs/Q/9HW1//T2Nr/0tfZ/9PX2f/T1db50dPT7NDR0d3Nzs7Xz8/Pwc/P
|
||||
z63U1NSP0NDQdNLS0k/Ozs8rysrKFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAALCytb2zra7/hTgw/5FKQ/+cZV//roF7/7GSjv+xoaD/tLGy/7vB
|
||||
w/+/ys3/xdDT/8rU1v/N1db/ztPU983P0OvNzs7dy8vL1MvLy8HKysqmzs7Oj8vLzHnOzs5Oy8vLM8rK
|
||||
yhrKysoDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK2tr7PCw8P/t7/C/73Fx//Dy83/xMrM/cXJ
|
||||
y/XHycrqxsfI3MbGx83Hx8jAx8fHp8rKyovIyMhzy8vLUsrKyjnKysoaysrKCwAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCgo3a5ubvAvLy9wr+/
|
||||
wK28vL6NwMDBb8LCw1fHx8g8ysrKIMrKyhQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AADKysoOysrKAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//4AD//8AAP/8
|
||||
AAD4fwAA//AAACAPAAD/4AAAAAcAAP/AAAAAAQAA/4AAAAABAAD/gAAAAAEAAP+AAAAAAQAA/4AAAAAB
|
||||
AAD/wAAAAAEAAP/gAAAAAAAA//AAAAAHAAD/hAAAAH8AAP4BAAAAfwAA/4AAAAB/AAD8AAAAAH8AAMAA
|
||||
AAAAfwAAgAAAAAB/AACAAAAAAH8AAIAAAAAAPwAAgAAAAAA/AACAAAAAAD8AAIAAAAAAPwAAwAAAAAA/
|
||||
AADAAAAAAD8AAMAAAAAAPwAAwAAAAAA/AADAAAAAAD8AAMAAAAAAHwAAwAAAAAAfAADgAAAAAB8AAOAA
|
||||
AAAAHwAA4AAAAAAfAADgAAAAAB8AAOAAAAAAHwAA4AAAAAAfAADgAAAAAA8AAPAAAAAADwAA8AAAAAAP
|
||||
AADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAB8AAPAAAAAD/wAA+AAAAf//AAD4AAH///8AAPgB
|
||||
/////wAA/P//////AAA=
|
||||
</value>
|
||||
</data>
|
||||
<data name="$this.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>3, 2, 3, 2</value>
|
||||
</data>
|
||||
<data name="$this.StartPosition" type="System.Windows.Forms.FormStartPosition, System.Windows.Forms">
|
||||
<value>CenterScreen</value>
|
||||
</data>
|
||||
<data name="$this.Text" xml:space="preserve">
|
||||
<value>Remote Desktop</value>
|
||||
</data>
|
||||
<data name=">>$this.Name" xml:space="preserve">
|
||||
<value>KVMViewerExtra</value>
|
||||
</data>
|
||||
<data name=">>$this.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
</root>
|
||||
393
ListViewExtended.cs
Normal file
393
ListViewExtended.cs
Normal file
@@ -0,0 +1,393 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Reflection;
|
||||
|
||||
namespace MeshCentralRouter
|
||||
{
|
||||
public class ListViewExtended : ListView
|
||||
{
|
||||
private const int LVM_FIRST = 0x1000; // ListView messages
|
||||
private const int LVM_SETGROUPINFO = (LVM_FIRST + 147); // ListView messages Setinfo on Group
|
||||
private const int WM_LBUTTONUP = 0x0202; // Windows message left button
|
||||
|
||||
private delegate void CallBackSetGroupState(ListViewGroup lstvwgrp, ListViewGroupState state);
|
||||
private delegate void CallbackSetGroupString(ListViewGroup lstvwgrp, string value);
|
||||
|
||||
/// <summary>
|
||||
/// Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window and does not return until the window procedure has processed the message.
|
||||
/// To send a message and return immediately, use the SendMessageCallback or SendNotifyMessage function. To post a message to a thread's message queue and return immediately, use the PostMessage or PostThreadMessage function.
|
||||
/// </summary>
|
||||
/// <param name="hWnd">
|
||||
/// [in] Handle to the window whose window procedure will receive the message.
|
||||
/// If this parameter is HWND_BROADCAST, the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows.
|
||||
/// Microsoft Windows Vista and later. Message sending is subject to User Interface Privilege Isolation (UIPI). The thread of a process can send messages only to message queues of threads in processes of lesser or equal integrity level.
|
||||
/// </param>
|
||||
/// <param name="uMsg">[in] Specifies the message to be sent.</param>
|
||||
/// <param name="wParam">[in] Specifies additional message-specific information.</param>
|
||||
/// <param name="lParam">[in] Type of LVGROUP, Specifies additional message-specific information.</param>
|
||||
/// <returns>
|
||||
/// Microsoft Windows Vista and later. When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).
|
||||
/// Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a unique message for inter-application communication.
|
||||
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= WM_USER) to another process, you must do custom marshalling.
|
||||
/// If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. For more information on nonqueued messages, see Nonqueued Messages.
|
||||
/// Windows 95/98/Me: SendMessageW is supported by the Microsoft Layer for Unicode (MSLU). To use this, you must add certain files to your application, as outlined in Microsoft Layer for Unicode on Windows 95/98/Me Systems.
|
||||
/// </returns>
|
||||
[DllImport("User32.dll"), Description("Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window and does not return until the window procedure has processed the message. To send a message and return immediately, use the SendMessageCallback or SendNotifyMessage function. To post a message to a thread's message queue and return immediately, use the PostMessage or PostThreadMessage function.")]
|
||||
private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, LVGROUP lParam);
|
||||
|
||||
private static int? GetGroupID(ListViewGroup lstvwgrp)
|
||||
{
|
||||
int? rtnval = null;
|
||||
Type GrpTp = lstvwgrp.GetType();
|
||||
if (GrpTp != null)
|
||||
{
|
||||
PropertyInfo pi = GrpTp.GetProperty("ID", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (pi != null)
|
||||
{
|
||||
object tmprtnval = pi.GetValue(lstvwgrp, null);
|
||||
if (tmprtnval != null)
|
||||
{
|
||||
rtnval = tmprtnval as int?;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rtnval;
|
||||
}
|
||||
|
||||
public static void setGrpState(ListViewGroup lstvwgrp, ListViewGroupState state)
|
||||
{
|
||||
if (Environment.OSVersion.Version.Major < 6) //Only Vista and forward allows collaps of ListViewGroups
|
||||
return;
|
||||
if (lstvwgrp == null || lstvwgrp.ListView == null)
|
||||
return;
|
||||
if (lstvwgrp.ListView.InvokeRequired)
|
||||
lstvwgrp.ListView.Invoke(new CallBackSetGroupState(setGrpState), lstvwgrp, state);
|
||||
else
|
||||
{
|
||||
int? GrpId = GetGroupID(lstvwgrp);
|
||||
int gIndex = lstvwgrp.ListView.Groups.IndexOf(lstvwgrp);
|
||||
LVGROUP group = new LVGROUP();
|
||||
group.CbSize = Marshal.SizeOf(group);
|
||||
group.State = state;
|
||||
group.Mask = ListViewGroupMask.State;
|
||||
if (GrpId != null)
|
||||
{
|
||||
group.IGroupId = GrpId.Value;
|
||||
SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, GrpId.Value, group);
|
||||
SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, GrpId.Value, group);
|
||||
}
|
||||
else
|
||||
{
|
||||
group.IGroupId = gIndex;
|
||||
SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, gIndex, group);
|
||||
SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, gIndex, group);
|
||||
}
|
||||
lstvwgrp.ListView.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private static void setGrpFooter(ListViewGroup lstvwgrp, string footer)
|
||||
{
|
||||
if (Environment.OSVersion.Version.Major < 6) //Only Vista and forward allows footer on ListViewGroups
|
||||
return;
|
||||
if (lstvwgrp == null || lstvwgrp.ListView == null)
|
||||
return;
|
||||
if (lstvwgrp.ListView.InvokeRequired)
|
||||
lstvwgrp.ListView.Invoke(new CallbackSetGroupString(setGrpFooter), lstvwgrp, footer);
|
||||
else
|
||||
{
|
||||
int? GrpId = GetGroupID(lstvwgrp);
|
||||
int gIndex = lstvwgrp.ListView.Groups.IndexOf(lstvwgrp);
|
||||
LVGROUP group = new LVGROUP();
|
||||
group.CbSize = Marshal.SizeOf(group);
|
||||
group.PszFooter = footer;
|
||||
group.Mask = ListViewGroupMask.Footer;
|
||||
if (GrpId != null)
|
||||
{
|
||||
group.IGroupId = GrpId.Value;
|
||||
SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, GrpId.Value, group);
|
||||
}
|
||||
else
|
||||
{
|
||||
group.IGroupId = gIndex;
|
||||
SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, gIndex, group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetGroupState(ListViewGroupState state)
|
||||
{
|
||||
foreach (ListViewGroup lvg in this.Groups)
|
||||
setGrpState(lvg, state);
|
||||
}
|
||||
|
||||
public void SetGroupFooter(ListViewGroup lvg, string footerText)
|
||||
{
|
||||
setGrpFooter(lvg, footerText);
|
||||
}
|
||||
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
if (m.Msg == WM_LBUTTONUP)
|
||||
base.DefWndProc(ref m);
|
||||
base.WndProc(ref m);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// LVGROUP StructureUsed to set and retrieve groups.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// LVGROUP myLVGROUP = new LVGROUP();
|
||||
/// myLVGROUP.CbSize // is of managed type uint
|
||||
/// myLVGROUP.Mask // is of managed type uint
|
||||
/// myLVGROUP.PszHeader // is of managed type string
|
||||
/// myLVGROUP.CchHeader // is of managed type int
|
||||
/// myLVGROUP.PszFooter // is of managed type string
|
||||
/// myLVGROUP.CchFooter // is of managed type int
|
||||
/// myLVGROUP.IGroupId // is of managed type int
|
||||
/// myLVGROUP.StateMask // is of managed type uint
|
||||
/// myLVGROUP.State // is of managed type uint
|
||||
/// myLVGROUP.UAlign // is of managed type uint
|
||||
/// myLVGROUP.PszSubtitle // is of managed type IntPtr
|
||||
/// myLVGROUP.CchSubtitle // is of managed type uint
|
||||
/// myLVGROUP.PszTask // is of managed type string
|
||||
/// myLVGROUP.CchTask // is of managed type uint
|
||||
/// myLVGROUP.PszDescriptionTop // is of managed type string
|
||||
/// myLVGROUP.CchDescriptionTop // is of managed type uint
|
||||
/// myLVGROUP.PszDescriptionBottom // is of managed type string
|
||||
/// myLVGROUP.CchDescriptionBottom // is of managed type uint
|
||||
/// myLVGROUP.ITitleImage // is of managed type int
|
||||
/// myLVGROUP.IExtendedImage // is of managed type int
|
||||
/// myLVGROUP.IFirstItem // is of managed type int
|
||||
/// myLVGROUP.CItems // is of managed type IntPtr
|
||||
/// myLVGROUP.PszSubsetTitle // is of managed type IntPtr
|
||||
/// myLVGROUP.CchSubsetTitle // is of managed type IntPtr
|
||||
/// </example>
|
||||
/// <remarks>
|
||||
/// The LVGROUP structure was created by Paw Jershauge
|
||||
/// Created: Jan. 2008.
|
||||
/// The LVGROUP structure code is based on information from Microsoft's MSDN2 website.
|
||||
/// The structure is generated via an automated converter and is as is.
|
||||
/// The structure may or may not hold errors inside the code, so use at own risk.
|
||||
/// Reference url: http://msdn.microsoft.com/en-us/library/bb774769(VS.85).aspx
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode), Description("LVGROUP StructureUsed to set and retrieve groups.")]
|
||||
public struct LVGROUP
|
||||
{
|
||||
/// <summary>
|
||||
/// Size of this structure, in bytes.
|
||||
/// </summary>
|
||||
[Description("Size of this structure, in bytes.")]
|
||||
public int CbSize;
|
||||
|
||||
/// <summary>
|
||||
/// Mask that specifies which members of the structure are valid input. One or more of the following values:LVGF_NONENo other items are valid.
|
||||
/// </summary>
|
||||
[Description("Mask that specifies which members of the structure are valid input. One or more of the following values:LVGF_NONE No other items are valid.")]
|
||||
public ListViewGroupMask Mask;
|
||||
|
||||
/// <summary>
|
||||
/// Pointer to a null-terminated string that contains the header text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the header text.
|
||||
/// </summary>
|
||||
[Description("Pointer to a null-terminated string that contains the header text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the header text.")]
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string PszHeader;
|
||||
|
||||
/// <summary>
|
||||
/// Size in TCHARs of the buffer pointed to by the pszHeader member. If the structure is not receiving information about a group, this member is ignored.
|
||||
/// </summary>
|
||||
[Description("Size in TCHARs of the buffer pointed to by the pszHeader member. If the structure is not receiving information about a group, this member is ignored.")]
|
||||
public int CchHeader;
|
||||
|
||||
/// <summary>
|
||||
/// Pointer to a null-terminated string that contains the footer text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the footer text.
|
||||
/// </summary>
|
||||
[Description("Pointer to a null-terminated string that contains the footer text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the footer text.")]
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string PszFooter;
|
||||
|
||||
/// <summary>
|
||||
/// Size in TCHARs of the buffer pointed to by the pszFooter member. If the structure is not receiving information about a group, this member is ignored.
|
||||
/// </summary>
|
||||
[Description("Size in TCHARs of the buffer pointed to by the pszFooter member. If the structure is not receiving information about a group, this member is ignored.")]
|
||||
public int CchFooter;
|
||||
|
||||
/// <summary>
|
||||
/// ID of the group.
|
||||
/// </summary>
|
||||
[Description("ID of the group.")]
|
||||
public int IGroupId;
|
||||
|
||||
/// <summary>
|
||||
/// Mask used with LVM_GETGROUPINFO (Microsoft Windows XP and Windows Vista) and LVM_SETGROUPINFO (Windows Vista only) to specify which flags in the state value are being retrieved or set.
|
||||
/// </summary>
|
||||
[Description("Mask used with LVM_GETGROUPINFO (Microsoft Windows XP and Windows Vista) and LVM_SETGROUPINFO (Windows Vista only) to specify which flags in the state value are being retrieved or set.")]
|
||||
public int StateMask;
|
||||
|
||||
/// <summary>
|
||||
/// Flag that can have one of the following values:LVGS_NORMALGroups are expanded, the group name is displayed, and all items in the group are displayed.
|
||||
/// </summary>
|
||||
[Description("Flag that can have one of the following values:LVGS_NORMAL Groups are expanded, the group name is displayed, and all items in the group are displayed.")]
|
||||
public ListViewGroupState State;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the alignment of the header or footer text for the group. It can have one or more of the following values. Use one of the header flags. Footer flags are optional. Windows XP: Footer flags are reserved.LVGA_FOOTER_CENTERReserved.
|
||||
/// </summary>
|
||||
[Description("Indicates the alignment of the header or footer text for the group. It can have one or more of the following values. Use one of the header flags. Footer flags are optional. Windows XP: Footer flags are reserved.LVGA_FOOTER_CENTERReserved.")]
|
||||
public uint UAlign;
|
||||
|
||||
/// <summary>
|
||||
/// Windows Vista. Pointer to a null-terminated string that contains the subtitle text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the subtitle text. This element is drawn under the header text.
|
||||
/// </summary>
|
||||
[Description("Windows Vista. Pointer to a null-terminated string that contains the subtitle text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the subtitle text. This element is drawn under the header text.")]
|
||||
public IntPtr PszSubtitle;
|
||||
|
||||
/// <summary>
|
||||
/// Windows Vista. Size, in TCHARs, of the buffer pointed to by the pszSubtitle member. If the structure is not receiving information about a group, this member is ignored.
|
||||
/// </summary>
|
||||
[Description("Windows Vista. Size, in TCHARs, of the buffer pointed to by the pszSubtitle member. If the structure is not receiving information about a group, this member is ignored.")]
|
||||
public uint CchSubtitle;
|
||||
|
||||
/// <summary>
|
||||
/// Windows Vista. Pointer to a null-terminated string that contains the text for a task link when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the task text. This item is drawn right-aligned opposite the header text. When clicked by the user, the task link generates an LVN_LINKCLICK notification.
|
||||
/// </summary>
|
||||
[Description("Windows Vista. Pointer to a null-terminated string that contains the text for a task link when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the task text. This item is drawn right-aligned opposite the header text. When clicked by the user, the task link generates an LVN_LINKCLICK notification.")]
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string PszTask;
|
||||
|
||||
/// <summary>
|
||||
/// Windows Vista. Size in TCHARs of the buffer pointed to by the pszTask member. If the structure is not receiving information about a group, this member is ignored.
|
||||
/// </summary>
|
||||
[Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszTask member. If the structure is not receiving information about a group, this member is ignored.")]
|
||||
public uint CchTask;
|
||||
|
||||
/// <summary>
|
||||
/// Windows Vista. Pointer to a null-terminated string that contains the top description text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the top description text. This item is drawn opposite the title image when there is a title image, no extended image, and uAlign==LVGA_HEADER_CENTER.
|
||||
/// </summary>
|
||||
[Description("Windows Vista. Pointer to a null-terminated string that contains the top description text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the top description text. This item is drawn opposite the title image when there is a title image, no extended image, and uAlign==LVGA_HEADER_CENTER.")]
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string PszDescriptionTop;
|
||||
|
||||
/// <summary>
|
||||
/// Windows Vista. Size in TCHARs of the buffer pointed to by the pszDescriptionTop member. If the structure is not receiving information about a group, this member is ignored.
|
||||
/// </summary>
|
||||
[Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszDescriptionTop member. If the structure is not receiving information about a group, this member is ignored.")]
|
||||
public uint CchDescriptionTop;
|
||||
|
||||
/// <summary>
|
||||
/// Windows Vista. Pointer to a null-terminated string that contains the bottom description text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the bottom description text. This item is drawn under the top description text when there is a title image, no extended image, and uAlign==LVGA_HEADER_CENTER.
|
||||
/// </summary>
|
||||
[Description("Windows Vista. Pointer to a null-terminated string that contains the bottom description text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the bottom description text. This item is drawn under the top description text when there is a title image, no extended image, and uAlign==LVGA_HEADER_CENTER.")]
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string PszDescriptionBottom;
|
||||
|
||||
/// <summary>
|
||||
/// Windows Vista. Size in TCHARs of the buffer pointed to by the pszDescriptionBottom member. If the structure is not receiving information about a group, this member is ignored.
|
||||
/// </summary>
|
||||
[Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszDescriptionBottom member. If the structure is not receiving information about a group, this member is ignored.")]
|
||||
public uint CchDescriptionBottom;
|
||||
|
||||
/// <summary>
|
||||
/// Windows Vista. Index of the title image in the control imagelist.
|
||||
/// </summary>
|
||||
[Description("Windows Vista. Index of the title image in the control imagelist.")]
|
||||
public int ITitleImage;
|
||||
|
||||
/// <summary>
|
||||
/// Windows Vista. Index of the extended image in the control imagelist.
|
||||
/// </summary>
|
||||
[Description("Windows Vista. Index of the extended image in the control imagelist.")]
|
||||
public int IExtendedImage;
|
||||
|
||||
/// <summary>
|
||||
/// Windows Vista. Read-only.
|
||||
/// </summary>
|
||||
[Description("Windows Vista. Read-only.")]
|
||||
public int IFirstItem;
|
||||
|
||||
/// <summary>
|
||||
/// Windows Vista. Read-only in non-owner data mode.
|
||||
/// </summary>
|
||||
[Description("Windows Vista. Read-only in non-owner data mode.")]
|
||||
public IntPtr CItems;
|
||||
|
||||
/// <summary>
|
||||
/// Windows Vista. NULL if group is not a subset. Pointer to a null-terminated string that contains the subset title text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the subset title text.
|
||||
/// </summary>
|
||||
[Description("Windows Vista. NULL if group is not a subset. Pointer to a null-terminated string that contains the subset title text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the subset title text.")]
|
||||
public IntPtr PszSubsetTitle;
|
||||
|
||||
/// <summary>
|
||||
/// Windows Vista. Size in TCHARs of the buffer pointed to by the pszSubsetTitle member. If the structure is not receiving information about a group, this member is ignored.
|
||||
/// </summary>
|
||||
[Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszSubsetTitle member. If the structure is not receiving information about a group, this member is ignored.")]
|
||||
public IntPtr CchSubsetTitle;
|
||||
}
|
||||
|
||||
public enum ListViewGroupMask
|
||||
{
|
||||
None = 0x00000,
|
||||
Header = 0x00001,
|
||||
Footer = 0x00002,
|
||||
State = 0x00004,
|
||||
Align = 0x00008,
|
||||
GroupId = 0x00010,
|
||||
SubTitle = 0x00100,
|
||||
Task = 0x00200,
|
||||
DescriptionTop = 0x00400,
|
||||
DescriptionBottom = 0x00800,
|
||||
TitleImage = 0x01000,
|
||||
ExtendedImage = 0x02000,
|
||||
Items = 0x04000,
|
||||
Subset = 0x08000,
|
||||
SubsetItems = 0x10000
|
||||
}
|
||||
|
||||
public enum ListViewGroupState
|
||||
{
|
||||
/// <summary>
|
||||
/// Groups are expanded, the group name is displayed, and all items in the group are displayed.
|
||||
/// </summary>
|
||||
Normal = 0,
|
||||
/// <summary>
|
||||
/// The group is collapsed.
|
||||
/// </summary>
|
||||
Collapsed = 1,
|
||||
/// <summary>
|
||||
/// The group is hidden.
|
||||
/// </summary>
|
||||
Hidden = 2,
|
||||
/// <summary>
|
||||
/// Version 6.00 and Windows Vista. The group does not display a header.
|
||||
/// </summary>
|
||||
NoHeader = 4,
|
||||
/// <summary>
|
||||
/// Version 6.00 and Windows Vista. The group can be collapsed.
|
||||
/// </summary>
|
||||
Collapsible = 8,
|
||||
/// <summary>
|
||||
/// Version 6.00 and Windows Vista. The group has keyboard focus.
|
||||
/// </summary>
|
||||
Focused = 16,
|
||||
/// <summary>
|
||||
/// Version 6.00 and Windows Vista. The group is selected.
|
||||
/// </summary>
|
||||
Selected = 32,
|
||||
/// <summary>
|
||||
/// Version 6.00 and Windows Vista. The group displays only a portion of its items.
|
||||
/// </summary>
|
||||
SubSeted = 64,
|
||||
/// <summary>
|
||||
/// Version 6.00 and Windows Vista. The subset link of the group has keyboard focus.
|
||||
/// </summary>
|
||||
SubSetLinkFocused = 128,
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
26
MainForm.Designer.cs
generated
26
MainForm.Designer.cs
generated
@@ -89,7 +89,7 @@
|
||||
this.devicesTabPage = new System.Windows.Forms.TabPage();
|
||||
this.devicesPanel = new System.Windows.Forms.Panel();
|
||||
this.cancelAutoCloseButton1 = new System.Windows.Forms.Button();
|
||||
this.devicesListView = new System.Windows.Forms.ListView();
|
||||
this.devicesListView = new ListViewExtended();
|
||||
this.nameColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.stateColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.devicesContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
@@ -137,6 +137,8 @@
|
||||
this.settingsToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.openMapFileDialog = new System.Windows.Forms.OpenFileDialog();
|
||||
this.saveMapFileDialog = new System.Windows.Forms.SaveFileDialog();
|
||||
this.customAppsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.customAppsToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.panel5.SuspendLayout();
|
||||
this.mainPanel.SuspendLayout();
|
||||
this.mainTabControl.SuspendLayout();
|
||||
@@ -524,7 +526,8 @@
|
||||
this.sortByNameToolStripMenuItem,
|
||||
this.sortByGroupToolStripMenuItem,
|
||||
this.toolStripMenuItem4,
|
||||
this.settingsToolStripMenuItem});
|
||||
this.settingsToolStripMenuItem,
|
||||
this.customAppsToolStripMenuItem1});
|
||||
this.mainContextMenuStrip.Name = "mainContextMenuStrip";
|
||||
resources.ApplyResources(this.mainContextMenuStrip, "mainContextMenuStrip");
|
||||
//
|
||||
@@ -937,7 +940,8 @@
|
||||
this.openMappingsToolStripMenuItem,
|
||||
this.saveMappingsToolStripMenuItem,
|
||||
this.toolStripMenuItem5,
|
||||
this.settingsToolStripMenuItem1});
|
||||
this.settingsToolStripMenuItem1,
|
||||
this.customAppsToolStripMenuItem});
|
||||
this.mappingsContextMenuStrip.Name = "mappingsContextMenuStrip";
|
||||
resources.ApplyResources(this.mappingsContextMenuStrip, "mappingsContextMenuStrip");
|
||||
//
|
||||
@@ -974,6 +978,18 @@
|
||||
this.saveMapFileDialog.DefaultExt = "mcrouter";
|
||||
resources.ApplyResources(this.saveMapFileDialog, "saveMapFileDialog");
|
||||
//
|
||||
// customAppsToolStripMenuItem
|
||||
//
|
||||
this.customAppsToolStripMenuItem.Name = "customAppsToolStripMenuItem";
|
||||
resources.ApplyResources(this.customAppsToolStripMenuItem, "customAppsToolStripMenuItem");
|
||||
this.customAppsToolStripMenuItem.Click += new System.EventHandler(this.customAppsToolStripMenuItem_Click);
|
||||
//
|
||||
// customAppsToolStripMenuItem1
|
||||
//
|
||||
this.customAppsToolStripMenuItem1.Name = "customAppsToolStripMenuItem1";
|
||||
resources.ApplyResources(this.customAppsToolStripMenuItem1, "customAppsToolStripMenuItem1");
|
||||
this.customAppsToolStripMenuItem1.Click += new System.EventHandler(this.customAppsToolStripMenuItem_Click);
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
resources.ApplyResources(this, "$this");
|
||||
@@ -1102,7 +1118,7 @@
|
||||
private System.Windows.Forms.ToolStripMenuItem saveMappingsToolStripMenuItem;
|
||||
private System.Windows.Forms.OpenFileDialog openMapFileDialog;
|
||||
private System.Windows.Forms.SaveFileDialog saveMapFileDialog;
|
||||
private System.Windows.Forms.ListView devicesListView;
|
||||
private ListViewExtended devicesListView;
|
||||
private System.Windows.Forms.ImageList devicesImageList;
|
||||
private System.Windows.Forms.ColumnHeader nameColumnHeader;
|
||||
private System.Windows.Forms.ColumnHeader stateColumnHeader;
|
||||
@@ -1131,6 +1147,8 @@
|
||||
private System.Windows.Forms.ToolStripMenuItem privacyBarToolStripMenuItem;
|
||||
private System.Windows.Forms.PictureBox pictureBox2;
|
||||
private System.Windows.Forms.Button proxySettings;
|
||||
private System.Windows.Forms.ToolStripMenuItem customAppsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem customAppsToolStripMenuItem1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
328
MainForm.cs
328
MainForm.cs
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -29,6 +29,7 @@ using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.Win32;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
|
||||
namespace MeshCentralRouter
|
||||
{
|
||||
@@ -123,7 +124,9 @@ namespace MeshCentralRouter
|
||||
try { installProcess = System.Diagnostics.Process.Start(startInfo); } catch (Exception) { return; }
|
||||
installTimer.Enabled = true;
|
||||
installButton.Visible = false;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
hookRouter();
|
||||
installButton.Visible = !isRouterHooked();
|
||||
}
|
||||
@@ -145,8 +148,6 @@ namespace MeshCentralRouter
|
||||
return principal.IsInRole(WindowsBuiltInRole.Administrator);
|
||||
}
|
||||
|
||||
public void DeleteSubKeyTree(RegistryKey key, string subkey) { if (key.OpenSubKey(subkey) == null) { return; } DeleteSubKeyTree(key, subkey); }
|
||||
|
||||
public class DeviceComparer : IComparer
|
||||
{
|
||||
public int Compare(Object a, Object b)
|
||||
@@ -170,11 +171,32 @@ namespace MeshCentralRouter
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||
private static extern Int32 SendMessage(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)]string lParam);
|
||||
|
||||
private bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
if (meshcentral.ignoreCert) return true;
|
||||
if (meshcentral.connectionState < 2)
|
||||
{
|
||||
// Normal certificate check
|
||||
if (chain.Build(new X509Certificate2(certificate)) == true) { meshcentral.certHash = webSocketClient.GetMeshKeyHash(certificate); return true; }
|
||||
if ((meshcentral.okCertHash != null) && ((meshcentral.okCertHash == certificate.GetCertHashString()) || (meshcentral.okCertHash == webSocketClient.GetMeshKeyHash(certificate)) || (meshcentral.okCertHash == webSocketClient.GetMeshCertHash(certificate)))) { meshcentral.certHash = webSocketClient.GetMeshKeyHash(certificate); return true; }
|
||||
if ((meshcentral.okCertHash2 != null) && ((meshcentral.okCertHash2 == certificate.GetCertHashString()) || (meshcentral.okCertHash2 == webSocketClient.GetMeshKeyHash(certificate)) || (meshcentral.okCertHash2 == webSocketClient.GetMeshCertHash(certificate)))) { meshcentral.certHash = webSocketClient.GetMeshKeyHash(certificate); return true; }
|
||||
meshcentral.certHash = null;
|
||||
meshcentral.disconnectMsg = "cert";
|
||||
meshcentral.disconnectCert = new X509Certificate2(certificate);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((meshcentral.certHash != null) && ((meshcentral.certHash == certificate.GetCertHashString()) || (meshcentral.certHash == webSocketClient.GetMeshKeyHash(certificate)) || (meshcentral.certHash == webSocketClient.GetMeshCertHash(certificate)))) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public MainForm(string[] args)
|
||||
{
|
||||
// Set TLS 1.2
|
||||
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
|
||||
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(RemoteCertificateValidationCallback);
|
||||
|
||||
this.args = args;
|
||||
InitializeComponent();
|
||||
@@ -193,10 +215,7 @@ namespace MeshCentralRouter
|
||||
versionLabel.Text = "v" + version.Major + "." + version.Minor + "." + version.Build;
|
||||
|
||||
// Prevent edgecase where the hook priority can be on and the hook disabled causing havoc
|
||||
if( !Settings.GetRegValue("Exp_KeyboardHook", false) )
|
||||
{
|
||||
Settings.SetRegValue("Exp_KeyboardHookPriority", false);
|
||||
}
|
||||
if (!Settings.GetRegValue("Exp_KeyboardHook", false)) { Settings.SetRegValue("Exp_KeyboardHookPriority", false); }
|
||||
|
||||
serverNameComboBox.Text = Settings.GetRegValue("ServerName", "");
|
||||
userNameTextBox.Text = Settings.GetRegValue("UserName", "");
|
||||
@@ -205,7 +224,8 @@ namespace MeshCentralRouter
|
||||
int argflags = 0;
|
||||
string update = null;
|
||||
string delete = null;
|
||||
foreach (string arg in this.args) {
|
||||
foreach (string arg in this.args)
|
||||
{
|
||||
if (arg.ToLower() == "-oldstyle") { deviceListViewMode = false; }
|
||||
if (arg.ToLower() == "-install") { hookRouter(); forceExit = true; return; }
|
||||
if (arg.ToLower() == "-uninstall") { unHookRouter(); forceExit = true; return; }
|
||||
@@ -215,6 +235,7 @@ namespace MeshCentralRouter
|
||||
if (arg.ToLower() == "-all") { inaddrany = true; }
|
||||
if (arg.ToLower() == "-inaddrany") { inaddrany = true; }
|
||||
if (arg.ToLower() == "-tray") { notifyIcon.Visible = true; this.ShowInTaskbar = false; this.MinimizeBox = false; }
|
||||
if (arg.ToLower() == "-native") { webSocketClient.nativeWebSocketFirst = true; }
|
||||
if (arg.Length > 6 && arg.Substring(0, 6).ToLower() == "-host:") { serverNameComboBox.Text = arg.Substring(6); argflags |= 1; }
|
||||
if (arg.Length > 6 && arg.Substring(0, 6).ToLower() == "-user:") { userNameTextBox.Text = arg.Substring(6); argflags |= 2; }
|
||||
if (arg.Length > 6 && arg.Substring(0, 6).ToLower() == "-pass:") { passwordTextBox.Text = arg.Substring(6); argflags |= 4; }
|
||||
@@ -227,7 +248,8 @@ namespace MeshCentralRouter
|
||||
}
|
||||
autoLogin = (argflags == 7);
|
||||
|
||||
if (update != null) {
|
||||
if (update != null)
|
||||
{
|
||||
// New args
|
||||
ArrayList args2 = new ArrayList();
|
||||
foreach (string a in args) { if (a.StartsWith("-update:") == false) { args2.Add(a); } }
|
||||
@@ -245,35 +267,43 @@ namespace MeshCentralRouter
|
||||
if (delete != null) { try { System.Threading.Thread.Sleep(1000); File.Delete(delete); } catch (Exception) { } }
|
||||
|
||||
// Set automatic port map values
|
||||
if (authLoginUrl != null) {
|
||||
if (authLoginUrl != null)
|
||||
{
|
||||
string autoName = null;
|
||||
string autoNodeId = null;
|
||||
string autoRemoteIp = null;
|
||||
int autoRemotePort = 0;
|
||||
int autoLocalPort = 0;
|
||||
int autoProtocol = 0;
|
||||
int autoAppId = 0;
|
||||
string autoAppIdStr = null;
|
||||
bool autoExit = false;
|
||||
try
|
||||
{
|
||||
// Automatic mappings
|
||||
autoName = getValueFromQueryString(authLoginUrl.Query, "name");
|
||||
autoNodeId = getValueFromQueryString(authLoginUrl.Query, "nodeid");
|
||||
autoRemoteIp = getValueFromQueryString(authLoginUrl.Query, "remoteip");
|
||||
int.TryParse(getValueFromQueryString(authLoginUrl.Query, "remoteport"), out autoRemotePort);
|
||||
int.TryParse(getValueFromQueryString(authLoginUrl.Query, "protocol"), out autoProtocol);
|
||||
int.TryParse(getValueFromQueryString(authLoginUrl.Query, "appid"), out autoAppId);
|
||||
autoExit = (getValueFromQueryString(authLoginUrl.Query, "autoexit") == "1");
|
||||
string localPortStr = getValueFromQueryString(authLoginUrl.Query, "localport");
|
||||
if (localPortStr != null) { autoLocalPort = int.Parse(localPortStr); }
|
||||
autoAppIdStr = getValueFromQueryString(authLoginUrl.Query, "appid");
|
||||
int.TryParse(autoAppIdStr, out autoAppId);
|
||||
}
|
||||
catch (Exception) { }
|
||||
if (((autoRemotePort != 0) && (autoProtocol != 0) && (autoNodeId != null)) || ((autoNodeId != null) && ((autoAppId == 6) || (autoAppId == 7)))) {
|
||||
if (((autoRemotePort != 0) && (autoProtocol != 0) && (autoNodeId != null)) || ((autoNodeId != null) && ((autoAppId == 6) || (autoAppId == 7))))
|
||||
{
|
||||
Dictionary<string, object> map = new Dictionary<string, object>();
|
||||
if (autoName != null) { map.Add("name", HttpUtility.UrlDecode(autoName)); }
|
||||
map.Add("nodeId", autoNodeId);
|
||||
if (autoRemoteIp != null) { map.Add("remoteIP", autoRemoteIp); }
|
||||
map.Add("remotePort", autoRemotePort);
|
||||
map.Add("localPort", autoLocalPort);
|
||||
map.Add("protocol", autoProtocol);
|
||||
map.Add("appId", autoAppId);
|
||||
map.Add("appIdStr", autoAppIdStr);
|
||||
map.Add("autoExit", autoExit);
|
||||
map.Add("launch", 1);
|
||||
mappingsToSetup = new ArrayList();
|
||||
@@ -354,10 +384,13 @@ namespace MeshCentralRouter
|
||||
// Load registry settings
|
||||
showGroupNamesToolStripMenuItem.Checked = (Settings.GetRegValue("Show Group Names", "1") == "1");
|
||||
showOfflineDevicesToolStripMenuItem.Checked = (Settings.GetRegValue("Show Offline Devices", "1") == "1");
|
||||
if (Settings.GetRegValue("Device Sort", "Name") == "Name") {
|
||||
if (Settings.GetRegValue("Device Sort", "Name") == "Name")
|
||||
{
|
||||
sortByNameToolStripMenuItem.Checked = true;
|
||||
sortByGroupToolStripMenuItem.Checked = false;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
sortByNameToolStripMenuItem.Checked = false;
|
||||
sortByGroupToolStripMenuItem.Checked = true;
|
||||
}
|
||||
@@ -504,16 +537,21 @@ namespace MeshCentralRouter
|
||||
if ((twoFactorCookie != null) && (twoFactorCookie != "")) { twoFactorCookie = "cookie=" + twoFactorCookie; } else { twoFactorCookie = null; }
|
||||
|
||||
Uri serverurl = null;
|
||||
if (authLoginUrl != null) {
|
||||
try {
|
||||
if (authLoginUrl != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
meshcentral.okCertHash2 = getValueFromQueryString(authLoginUrl.Query, "t");
|
||||
string loginkey = getValueFromQueryString(authLoginUrl.Query, "key");
|
||||
string urlstring = "wss://" + authLoginUrl.Host + ":" + ((authLoginUrl.Port > 0) ? authLoginUrl.Port : 443) + authLoginUrl.LocalPath + "?auth=" + getValueFromQueryString(authLoginUrl.Query, "c");
|
||||
if (loginkey != null) { urlstring += ("&key=" + loginkey); }
|
||||
serverurl = new Uri(urlstring);
|
||||
} catch (Exception) { }
|
||||
}
|
||||
catch (Exception) { }
|
||||
meshcentral.connect(serverurl, null, null, null);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
int keyIndex = serverNameComboBox.Text.IndexOf("?key=");
|
||||
if (keyIndex >= 0)
|
||||
{
|
||||
@@ -539,6 +577,7 @@ namespace MeshCentralRouter
|
||||
private void Meshcentral_onTwoFactorCookie(string cookie)
|
||||
{
|
||||
if (this.InvokeRequired) { this.Invoke(new MeshCentralServer.twoFactorCookieHandler(Meshcentral_onTwoFactorCookie), cookie); return; }
|
||||
if (debug) { try { File.AppendAllText("debug.log", "Saving 2FA cookie\r\n"); } catch (Exception) { } }
|
||||
Settings.SetRegValue("TwoFactorCookie", cookie);
|
||||
}
|
||||
|
||||
@@ -564,14 +603,17 @@ namespace MeshCentralRouter
|
||||
meshcentral.okCertHash = lastBadConnectCert.GetCertHashString();
|
||||
|
||||
Uri serverurl = null;
|
||||
if (authLoginUrl != null) {
|
||||
if (authLoginUrl != null)
|
||||
{
|
||||
meshcentral.okCertHash2 = getValueFromQueryString(authLoginUrl.Query, "t");
|
||||
string loginkey = getValueFromQueryString(authLoginUrl.Query, "key");
|
||||
string urlstring = "wss://" + authLoginUrl.Host + ":" + ((authLoginUrl.Port > 0) ? authLoginUrl.Port : 443) + authLoginUrl.LocalPath + "?auth=" + getValueFromQueryString(authLoginUrl.Query, "c");
|
||||
if (loginkey != null) { urlstring += ("&key=" + loginkey); }
|
||||
serverurl = new Uri(urlstring);
|
||||
meshcentral.connect(serverurl, null, null, null);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load two factor cookie if present
|
||||
string twoFactorCookie = Settings.GetRegValue("TwoFactorCookie", null);
|
||||
if ((twoFactorCookie != null) && (twoFactorCookie != "")) { twoFactorCookie = "cookie=" + twoFactorCookie; } else { twoFactorCookie = null; }
|
||||
@@ -625,9 +667,23 @@ namespace MeshCentralRouter
|
||||
|
||||
// Setup any automatic mappings
|
||||
if ((fullRefresh == true) && (mappingsToSetup != null)) { setupMappings(); }
|
||||
|
||||
// Reconnect any auto-reconnect nodes
|
||||
foreach (NodeClass node in meshcentral.nodes.Values)
|
||||
{
|
||||
if (((node.conn & 1) != 0) && (node.desktopViewer != null)) { node.desktopViewer.TryAutoConnect(); }
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDeviceList()
|
||||
class GroupComparer : IComparer
|
||||
{
|
||||
public int Compare(object objA, object objB)
|
||||
{
|
||||
return ((ListViewGroup)objA).Header.CompareTo(((ListViewGroup)objB).Header);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDeviceList()
|
||||
{
|
||||
string search = searchTextBox.Text.ToLower();
|
||||
if (deviceListViewMode)
|
||||
@@ -648,20 +704,60 @@ namespace MeshCentralRouter
|
||||
device.SubItems.Add(node.getStateString());
|
||||
device.Tag = node;
|
||||
node.listitem = device;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
device = node.listitem;
|
||||
device.SubItems[0].Text = node.name;
|
||||
device.SubItems[1].Text = node.getStateString();
|
||||
}
|
||||
|
||||
if ((node.meshid != null) && meshcentral.meshes.ContainsKey(node.meshid)) { node.mesh = (MeshClass)meshcentral.meshes[node.meshid]; }
|
||||
if ((showGroupNamesToolStripMenuItem.Checked) && (node.mesh != null)) {
|
||||
if ((showGroupNamesToolStripMenuItem.Checked) && (node.mesh != null))
|
||||
{
|
||||
device.SubItems[0].Text = node.mesh.name + " - " + node.name;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
device.SubItems[0].Text = node.name;
|
||||
}
|
||||
|
||||
bool connVisible = ((showOfflineDevicesToolStripMenuItem.Checked) || ((node.conn & 1) != 0)) || (node.mtype == 3);
|
||||
// *** Flynn Grouping start
|
||||
bool bGroupExisting = false;
|
||||
for(int i = 0; i < devicesListView.Groups.Count; i++)
|
||||
if(devicesListView.Groups[i].Header == node.mesh.name)
|
||||
{
|
||||
bGroupExisting = true;
|
||||
node.listitem.Group = devicesListView.Groups[i];
|
||||
break;
|
||||
}
|
||||
if(!bGroupExisting)
|
||||
{
|
||||
ListViewGroup grp = devicesListView.Groups.Add(devicesListView.Groups.Count.ToString(), node.mesh.name);
|
||||
node.listitem.Group = grp;
|
||||
|
||||
ListViewGroup[] groups = new ListViewGroup[this.devicesListView.Groups.Count];
|
||||
|
||||
this.devicesListView.Groups.CopyTo(groups, 0);
|
||||
|
||||
Array.Sort(groups, new GroupComparer());
|
||||
|
||||
this.devicesListView.BeginUpdate();
|
||||
this.devicesListView.Groups.Clear();
|
||||
this.devicesListView.Groups.AddRange(groups);
|
||||
this.devicesListView.EndUpdate();
|
||||
|
||||
foreach(ListViewGroup lvg in devicesListView.Groups)
|
||||
{
|
||||
if(lvg.Header == "Repos")
|
||||
ListViewExtended.setGrpState(lvg, ListViewGroupState.Collapsible | ListViewGroupState.Normal);
|
||||
else
|
||||
ListViewExtended.setGrpState(lvg, ListViewGroupState.Collapsible | ListViewGroupState.Collapsed);
|
||||
}
|
||||
}
|
||||
// *** Flynn Groupng end
|
||||
|
||||
bool connVisible = ((showOfflineDevicesToolStripMenuItem.Checked) || ((node.conn & 1) != 0)) || (node.mtype == 3);
|
||||
int imageIndex = (node.icon - 1) * 2;
|
||||
if (((node.conn & 1) == 0) && (node.mtype != 3)) { imageIndex++; }
|
||||
device.ImageIndex = imageIndex;
|
||||
@@ -674,7 +770,9 @@ namespace MeshCentralRouter
|
||||
{
|
||||
// Normal search
|
||||
if (connVisible && ((search == "") || (device.SubItems[0].Text.ToLower().IndexOf(search) >= 0))) { controlsToAdd.Add(device); }
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// User search
|
||||
bool userSearchMatch = false;
|
||||
if (node.users != null) { foreach (string user in node.users) { if (user.ToLower().IndexOf(userSearch) >= 0) { userSearchMatch = true; } } }
|
||||
@@ -683,7 +781,8 @@ namespace MeshCentralRouter
|
||||
}
|
||||
|
||||
// Add all controls at once to make it fast.
|
||||
if (controlsToAdd.Count > 0) {
|
||||
if (controlsToAdd.Count > 0)
|
||||
{
|
||||
devicesListView.Items.AddRange((ListViewItem[])controlsToAdd.ToArray(typeof(ListViewItem)));
|
||||
}
|
||||
}
|
||||
@@ -804,31 +903,41 @@ namespace MeshCentralRouter
|
||||
if (meshcentral == null) return;
|
||||
if (this.InvokeRequired) { this.Invoke(new MeshCentralServer.onStateChangedHandler(Meshcentral_onStateChanged), state); return; }
|
||||
|
||||
if (state == 0) {
|
||||
if (meshcentral.disconnectMsg == "tokenrequired") {
|
||||
if (state == 0)
|
||||
{
|
||||
if (meshcentral.disconnectMsg == "tokenrequired")
|
||||
{
|
||||
emailTokenButton.Visible = (meshcentral.disconnectEmail2FA == true) && (meshcentral.disconnectEmail2FASent == false);
|
||||
tokenEmailSentLabel.Visible = (meshcentral.disconnectEmail2FASent == true) || (meshcentral.disconnectSms2FASent == true);
|
||||
smsTokenButton.Visible = ((meshcentral.disconnectSms2FA == true) && (meshcentral.disconnectSms2FASent == false));
|
||||
if (meshcentral.disconnectEmail2FASent) { tokenEmailSentLabel.Text = Translate.T(Properties.Resources.EmailSent); }
|
||||
if (meshcentral.disconnectSms2FASent) { tokenEmailSentLabel.Text = Translate.T(Properties.Resources.SmsSent); }
|
||||
if ((meshcentral.disconnectEmail2FA == true) && (meshcentral.disconnectEmail2FASent == false)) {
|
||||
if ((meshcentral.disconnectEmail2FA == true) && (meshcentral.disconnectEmail2FASent == false))
|
||||
{
|
||||
smsTokenButton.Left = emailTokenButton.Left + emailTokenButton.Width + 5;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
smsTokenButton.Left = emailTokenButton.Left;
|
||||
}
|
||||
tokenTextBox.Text = "";
|
||||
if (meshcentral.twoFactorCookieDays > 0) {
|
||||
if (meshcentral.twoFactorCookieDays > 0)
|
||||
{
|
||||
tokenRememberCheckBox.Visible = true;
|
||||
tokenRememberCheckBox.Text = string.Format(Translate.T(Properties.Resources.DontAskXDays), meshcentral.twoFactorCookieDays);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
tokenRememberCheckBox.Visible = false;
|
||||
}
|
||||
|
||||
setPanel(2);
|
||||
tokenTextBox.Focus();
|
||||
} else { setPanel(1); }
|
||||
}
|
||||
else { setPanel(1); }
|
||||
|
||||
if ((meshcentral.disconnectMsg != null) && meshcentral.disconnectMsg.StartsWith("noauth")) {
|
||||
if ((meshcentral.disconnectMsg != null) && meshcentral.disconnectMsg.StartsWith("noauth"))
|
||||
{
|
||||
stateLabel.Text = Translate.T(Properties.Resources.InvalidUsernameOrPassword);
|
||||
stateLabel.Visible = true;
|
||||
stateClearTimer.Enabled = true;
|
||||
@@ -848,7 +957,8 @@ namespace MeshCentralRouter
|
||||
stateClearTimer.Enabled = true;
|
||||
serverNameComboBox.Focus();
|
||||
}
|
||||
else if (meshcentral.disconnectMsg == "cert") {
|
||||
else if (meshcentral.disconnectMsg == "cert")
|
||||
{
|
||||
lastBadConnectCert = meshcentral.disconnectCert;
|
||||
certDetailsTextBox.Text = "---Issuer---\r\n" + lastBadConnectCert.Issuer.Replace(", ", "\r\n") + "\r\n\r\n---Subject---\r\n" + lastBadConnectCert.Subject.Replace(", ", "\r\n");
|
||||
setPanel(3);
|
||||
@@ -864,14 +974,16 @@ namespace MeshCentralRouter
|
||||
this.Text = title;
|
||||
|
||||
// Clean up all mappings
|
||||
foreach (Control c in mapPanel.Controls) {
|
||||
foreach (Control c in mapPanel.Controls)
|
||||
{
|
||||
if (c.GetType() == typeof(MapUserControl)) { ((MapUserControl)c).Dispose(); }
|
||||
}
|
||||
mapPanel.Controls.Clear();
|
||||
noMapLabel.Visible = true;
|
||||
|
||||
// Clean up all devices (old style)
|
||||
foreach (Control c in devicesPanel.Controls) {
|
||||
foreach (Control c in devicesPanel.Controls)
|
||||
{
|
||||
if (c.GetType() == typeof(DeviceUserControl)) { ((DeviceUserControl)c).Dispose(); }
|
||||
}
|
||||
remoteAllDeviceControls();
|
||||
@@ -882,7 +994,8 @@ namespace MeshCentralRouter
|
||||
noDevicesLabel.Visible = true;
|
||||
if ((meshcentral != null) && (meshcentral.nodes != null))
|
||||
{
|
||||
foreach (NodeClass n in meshcentral.nodes.Values) {
|
||||
foreach (NodeClass n in meshcentral.nodes.Values)
|
||||
{
|
||||
if (n.desktopViewer != null) { n.desktopViewer.Close(); }
|
||||
if (n.fileViewer != null) { n.fileViewer.Close(); }
|
||||
}
|
||||
@@ -897,7 +1010,9 @@ namespace MeshCentralRouter
|
||||
meshcentral.onNodesChanged -= Meshcentral_onNodesChanged;
|
||||
meshcentral = null;
|
||||
authLoginUrl = null;
|
||||
} else if (state == 1) {
|
||||
}
|
||||
else if (state == 1)
|
||||
{
|
||||
stateLabel.Visible = false;
|
||||
//setPanel(1);
|
||||
nextButton1.Enabled = false;
|
||||
@@ -905,7 +1020,9 @@ namespace MeshCentralRouter
|
||||
userNameTextBox.Enabled = false;
|
||||
passwordTextBox.Enabled = false;
|
||||
cookieRefreshTimer.Enabled = false;
|
||||
} else if (state == 2) {
|
||||
}
|
||||
else if (state == 2)
|
||||
{
|
||||
meshcentral.disconnectMsg = "connected";
|
||||
stateLabel.Visible = false;
|
||||
setPanel(4);
|
||||
@@ -915,9 +1032,12 @@ namespace MeshCentralRouter
|
||||
Settings.SetRegValue("ServerName", serverNameComboBox.Text);
|
||||
Settings.SetRegValue("UserName", userNameTextBox.Text);
|
||||
}
|
||||
if (meshcentral.username != null) {
|
||||
if (meshcentral.username != null)
|
||||
{
|
||||
this.Text = title + " - " + meshcentral.username;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Text = title + " - " + userNameTextBox.Text;
|
||||
}
|
||||
cookieRefreshTimer.Enabled = true;
|
||||
@@ -926,7 +1046,8 @@ namespace MeshCentralRouter
|
||||
if (tokenRememberCheckBox.Checked) { meshcentral.sendCommand("{\"action\":\"twoFactorCookie\"}"); }
|
||||
|
||||
// Setup single instance pipe server
|
||||
if (authLoginUrl != null) {
|
||||
if (authLoginUrl != null)
|
||||
{
|
||||
string urlstring = "wss://" + authLoginUrl.Host + ":" + ((authLoginUrl.Port > 0) ? authLoginUrl.Port : 443) + authLoginUrl.LocalPath;
|
||||
localPipeServer = new LocalPipeServer(Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(urlstring))); // + "" + meshcentral.certHash
|
||||
localPipeServer.onArgs += LocalPipeServer_onArgs;
|
||||
@@ -946,21 +1067,25 @@ namespace MeshCentralRouter
|
||||
// Set automatic port map values
|
||||
if (authLoginUrl2 != null)
|
||||
{
|
||||
string autoName = null;
|
||||
string autoNodeId = null;
|
||||
string autoRemoteIp = null;
|
||||
int autoRemotePort = 0;
|
||||
int autoLocalPort = 0;
|
||||
int autoProtocol = 0;
|
||||
int autoAppId = 0;
|
||||
string autoAppIdStr = null;
|
||||
bool autoExit = false;
|
||||
try
|
||||
{
|
||||
// Automatic mappings
|
||||
autoName = getValueFromQueryString(authLoginUrl.Query, "name");
|
||||
autoNodeId = getValueFromQueryString(authLoginUrl2.Query, "nodeid");
|
||||
autoRemoteIp = getValueFromQueryString(authLoginUrl2.Query, "remoteip");
|
||||
int.TryParse(getValueFromQueryString(authLoginUrl2.Query, "remoteport"), out autoRemotePort);
|
||||
int.TryParse(getValueFromQueryString(authLoginUrl2.Query, "protocol"), out autoProtocol);
|
||||
int.TryParse(getValueFromQueryString(authLoginUrl2.Query, "appid"), out autoAppId);
|
||||
autoAppIdStr = getValueFromQueryString(authLoginUrl2.Query, "appid");
|
||||
int.TryParse(autoAppIdStr, out autoAppId);
|
||||
autoExit = (getValueFromQueryString(authLoginUrl2.Query, "autoexit") == "1");
|
||||
string localPortStr = getValueFromQueryString(authLoginUrl.Query, "localport");
|
||||
if (localPortStr != null) { autoLocalPort = int.Parse(localPortStr); }
|
||||
@@ -969,12 +1094,14 @@ namespace MeshCentralRouter
|
||||
if (((autoRemotePort != 0) && (autoProtocol != 0) && (autoNodeId != null)) || ((autoNodeId != null) && ((autoAppId == 6) || (autoAppId == 7))))
|
||||
{
|
||||
Dictionary<string, object> map = new Dictionary<string, object>();
|
||||
if (autoName != null) { map.Add("name", HttpUtility.UrlDecode(autoName)); }
|
||||
map.Add("nodeId", autoNodeId);
|
||||
if (autoRemoteIp != null) { map.Add("remoteIP", autoRemoteIp); }
|
||||
map.Add("remotePort", autoRemotePort);
|
||||
map.Add("localPort", autoLocalPort);
|
||||
map.Add("protocol", autoProtocol);
|
||||
map.Add("appId", autoAppId);
|
||||
map.Add("appIdStr", autoAppIdStr);
|
||||
map.Add("autoExit", autoExit);
|
||||
map.Add("launch", 1);
|
||||
mappingsToSetup = new ArrayList();
|
||||
@@ -995,7 +1122,8 @@ namespace MeshCentralRouter
|
||||
if ((map.protocol == 2) && (map.mapper.totalConnectCounter == 0))
|
||||
{
|
||||
// This is an unconnected UDP map, check if the target node is connected.
|
||||
foreach (NodeClass n in meshcentral.nodes.Values) {
|
||||
foreach (NodeClass n in meshcentral.nodes.Values)
|
||||
{
|
||||
if ((map.node == n) && ((n.conn & 1) != 0))
|
||||
{
|
||||
// Reconnect the UDP map
|
||||
@@ -1059,6 +1187,7 @@ namespace MeshCentralRouter
|
||||
map.localPort = (int)localPort;
|
||||
map.remotePort = (int)remotePort;
|
||||
map.appId = appId;
|
||||
if (appId == 0) { map.appIdStr = x[3].ToLower(); }
|
||||
map.node = node;
|
||||
if (authLoginUrl != null) { map.host = authLoginUrl.Host + ":" + ((authLoginUrl.Port > 0) ? authLoginUrl.Port : 443) + authLoginUrl.AbsolutePath.Replace("/control.ashx", ""); } else { map.host = serverNameComboBox.Text; }
|
||||
map.certhash = meshcentral.wshash;
|
||||
@@ -1120,6 +1249,7 @@ namespace MeshCentralRouter
|
||||
map.remoteIP = remoteIp.ToString();
|
||||
map.remotePort = (int)remotePort;
|
||||
map.appId = appId;
|
||||
if (appId == 0) { map.appIdStr = x[3].ToLower(); }
|
||||
map.node = node;
|
||||
if (authLoginUrl != null) { map.host = authLoginUrl.Host + ":" + ((authLoginUrl.Port > 0) ? authLoginUrl.Port : 443) + authLoginUrl.AbsolutePath.Replace("/control.ashx", ""); } else { map.host = serverNameComboBox.Text; }
|
||||
map.certhash = meshcentral.wshash;
|
||||
@@ -1160,6 +1290,7 @@ namespace MeshCentralRouter
|
||||
map.localPort = form.getLocalPort();
|
||||
map.remotePort = form.getRemotePort();
|
||||
map.appId = form.getAppId();
|
||||
map.appIdStr = form.getAppIdStr();
|
||||
map.node = form.getNode();
|
||||
if (authLoginUrl != null) { map.host = authLoginUrl.Host + ":" + ((authLoginUrl.Port > 0) ? authLoginUrl.Port : 443) + authLoginUrl.AbsolutePath.Replace("/control.ashx", ""); } else { map.host = serverNameComboBox.Text; }
|
||||
map.certhash = meshcentral.wshash;
|
||||
@@ -1193,12 +1324,15 @@ namespace MeshCentralRouter
|
||||
openWebSiteButton.Visible = false;
|
||||
|
||||
Uri serverurl = null;
|
||||
if (authLoginUrl != null) {
|
||||
if (authLoginUrl != null)
|
||||
{
|
||||
string loginkey = getValueFromQueryString(authLoginUrl.Query, "key");
|
||||
string urlstring = "wss://" + authLoginUrl.Host + ":" + ((authLoginUrl.Port > 0) ? authLoginUrl.Port : 443) + authLoginUrl.LocalPath + "?auth=" + getValueFromQueryString(authLoginUrl.Query, "c");
|
||||
if (loginkey != null) { urlstring += ("&key=" + loginkey); }
|
||||
serverurl = new Uri(urlstring);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
int keyIndex = serverNameComboBox.Text.IndexOf("?key=");
|
||||
if (keyIndex >= 0)
|
||||
{
|
||||
@@ -1216,9 +1350,12 @@ namespace MeshCentralRouter
|
||||
meshcentral.debug = debug;
|
||||
meshcentral.tlsdump = tlsdump;
|
||||
meshcentral.ignoreCert = ignoreCert;
|
||||
if (lastBadConnectCert != null) {
|
||||
if (lastBadConnectCert != null)
|
||||
{
|
||||
meshcentral.okCertHash = lastBadConnectCert.GetCertHashString();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
string ignoreCert = Settings.GetRegValue("IgnoreCert", null);
|
||||
if (ignoreCert != null) { meshcentral.okCertHash = ignoreCert; }
|
||||
}
|
||||
@@ -1318,6 +1455,7 @@ namespace MeshCentralRouter
|
||||
map.remotePort = form.getRemotePort();
|
||||
map.remoteIP = form.getRemoteIP();
|
||||
map.appId = form.getAppId();
|
||||
map.appIdStr = form.getAppIdStr();
|
||||
map.node = form.getNode();
|
||||
if (authLoginUrl != null) { map.host = authLoginUrl.Host + ":" + ((authLoginUrl.Port > 0) ? authLoginUrl.Port : 443) + authLoginUrl.AbsolutePath.Replace("/control.ashx", ""); } else { map.host = serverNameComboBox.Text; }
|
||||
map.certhash = meshcentral.wshash;
|
||||
@@ -1339,13 +1477,17 @@ namespace MeshCentralRouter
|
||||
private void openWebSiteButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
cancelAutoClose();
|
||||
if (meshcentral.loginCookie != null) {
|
||||
if (meshcentral.loginCookie != null)
|
||||
{
|
||||
Uri serverurl = null;
|
||||
if (authLoginUrl != null) {
|
||||
if (authLoginUrl != null)
|
||||
{
|
||||
string localPath = authLoginUrl.LocalPath;
|
||||
if (localPath.EndsWith("/control.ashx")) { localPath = localPath.Substring(0, localPath.Length - 12); }
|
||||
serverurl = new Uri("https://" + authLoginUrl.Host + ":" + ((authLoginUrl.Port > 0) ? authLoginUrl.Port : 443) + localPath + "?login=" + meshcentral.loginCookie);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
serverurl = new Uri("https://" + serverNameComboBox.Text + "?login=" + meshcentral.loginCookie);
|
||||
}
|
||||
System.Diagnostics.Process.Start(serverurl.ToString());
|
||||
@@ -1385,11 +1527,14 @@ namespace MeshCentralRouter
|
||||
if (f.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
inaddrany = f.BindAllInterfaces;
|
||||
if (f.ShowSystemTray) {
|
||||
if (f.ShowSystemTray)
|
||||
{
|
||||
notifyIcon.Visible = true;
|
||||
this.ShowInTaskbar = false;
|
||||
this.MinimizeBox = false;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
notifyIcon.Visible = false;
|
||||
this.ShowInTaskbar = true;
|
||||
this.MinimizeBox = true;
|
||||
@@ -1399,10 +1544,13 @@ namespace MeshCentralRouter
|
||||
|
||||
private void searchTextBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (deviceListViewMode) {
|
||||
if (deviceListViewMode)
|
||||
{
|
||||
// Filter devices
|
||||
updateDeviceList();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Filter devices
|
||||
int visibleDevices = 0;
|
||||
int deviceCount = 0;
|
||||
@@ -1436,9 +1584,12 @@ namespace MeshCentralRouter
|
||||
{
|
||||
cancelAutoClose();
|
||||
searchTextBox.Visible = (devicesTabControl.SelectedIndex == 0);
|
||||
if (devicesTabControl.SelectedIndex == 0) {
|
||||
if (devicesTabControl.SelectedIndex == 0)
|
||||
{
|
||||
menuLabel.ContextMenuStrip = mainContextMenuStrip;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
menuLabel.ContextMenuStrip = mappingsContextMenuStrip;
|
||||
}
|
||||
}
|
||||
@@ -1474,6 +1625,44 @@ namespace MeshCentralRouter
|
||||
map.localPort = 0; // Any
|
||||
map.remotePort = port; // HTTP
|
||||
map.appId = appId; // 0 = Custom, 1 = HTTP, 2 = HTTPS, 3 = RDP, 4 = PuTTY, 5 = WinSCP
|
||||
map.appIdStr = null;
|
||||
map.node = node;
|
||||
if (authLoginUrl != null) { map.host = authLoginUrl.Host + ":" + ((authLoginUrl.Port > 0) ? authLoginUrl.Port : 443) + authLoginUrl.AbsolutePath.Replace("/control.ashx", ""); } else { map.host = serverNameComboBox.Text; }
|
||||
map.certhash = meshcentral.wshash;
|
||||
map.parent = this;
|
||||
map.Dock = DockStyle.Top;
|
||||
map.Start();
|
||||
mapPanel.Controls.Add(map);
|
||||
noMapLabel.Visible = false;
|
||||
map.appButton_Click(this, null);
|
||||
}
|
||||
|
||||
public void QuickMap(int protocol, int port, string appIdStr, NodeClass node)
|
||||
{
|
||||
// See if we already have the right port mapping
|
||||
foreach (Control c in mapPanel.Controls)
|
||||
{
|
||||
if (c.GetType() == typeof(MapUserControl))
|
||||
{
|
||||
MapUserControl cc = (MapUserControl)c;
|
||||
if ((cc.protocol == protocol) && (cc.remotePort == port) && (cc.appIdStr == appIdStr) && (cc.node == node))
|
||||
{
|
||||
// Found a match
|
||||
cc.appButton_Click(this, null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add a new port map
|
||||
MapUserControl map = new MapUserControl();
|
||||
map.xdebug = debug;
|
||||
map.inaddrany = false; // Loopback only
|
||||
map.protocol = protocol; // 1 = TCP, 2 = UDP
|
||||
map.localPort = 0; // Any
|
||||
map.remotePort = port; // HTTP
|
||||
map.appId = 0; // 0 = Custom, 1 = HTTP, 2 = HTTPS, 3 = RDP, 4 = PuTTY, 5 = WinSCP
|
||||
map.appIdStr = appIdStr;
|
||||
map.node = node;
|
||||
if (authLoginUrl != null) { map.host = authLoginUrl.Host + ":" + ((authLoginUrl.Port > 0) ? authLoginUrl.Port : 443) + authLoginUrl.AbsolutePath.Replace("/control.ashx", ""); } else { map.host = serverNameComboBox.Text; }
|
||||
map.certhash = meshcentral.wshash;
|
||||
@@ -1507,7 +1696,7 @@ namespace MeshCentralRouter
|
||||
|
||||
private void tokenTextBox_KeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
nextButton2.Enabled = (tokenTextBox.Text.Replace(" ","") != "");
|
||||
nextButton2.Enabled = (tokenTextBox.Text.Replace(" ", "") != "");
|
||||
}
|
||||
|
||||
private void tokenTextBox_TextChanged(object sender, EventArgs e)
|
||||
@@ -1538,7 +1727,7 @@ namespace MeshCentralRouter
|
||||
private void hideOfflineDevicesToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
showOfflineDevicesToolStripMenuItem.Checked = !showOfflineDevicesToolStripMenuItem.Checked;
|
||||
Settings.SetRegValue("Show Offline Devices", showOfflineDevicesToolStripMenuItem.Checked?"1":"0");
|
||||
Settings.SetRegValue("Show Offline Devices", showOfflineDevicesToolStripMenuItem.Checked ? "1" : "0");
|
||||
updateDeviceList();
|
||||
}
|
||||
|
||||
@@ -1598,7 +1787,8 @@ namespace MeshCentralRouter
|
||||
if (jsonAction["mappings"] != null)
|
||||
{
|
||||
ArrayList mappings = (ArrayList)jsonAction["mappings"];
|
||||
if (mappings.Count > 0) {
|
||||
if (mappings.Count > 0)
|
||||
{
|
||||
mappingsToSetup = mappings;
|
||||
if (mode == 2) { setupMappings(); }
|
||||
}
|
||||
@@ -1650,9 +1840,10 @@ namespace MeshCentralRouter
|
||||
if (x.ContainsKey("remoteIP")) { map.remoteIP = (string)x["remoteIP"]; }
|
||||
map.remotePort = (int)x["remotePort"];
|
||||
map.appId = (int)x["appId"];
|
||||
if (x["appIdStr"] != null) { map.appIdStr = (string)x["appIdStr"]; }
|
||||
if (x.ContainsKey("autoExit")) { map.autoexit = (bool)x["autoExit"]; }
|
||||
map.node = node;
|
||||
if (authLoginUrl != null) { map.host = authLoginUrl.Host + ":" + ((authLoginUrl.Port > 0) ? authLoginUrl.Port : 443) + authLoginUrl.AbsolutePath.Replace("/control.ashx",""); } else { map.host = serverNameComboBox.Text; }
|
||||
if (authLoginUrl != null) { map.host = authLoginUrl.Host + ":" + ((authLoginUrl.Port > 0) ? authLoginUrl.Port : 443) + authLoginUrl.AbsolutePath.Replace("/control.ashx", ""); } else { map.host = serverNameComboBox.Text; }
|
||||
map.certhash = meshcentral.wshash;
|
||||
map.parent = this;
|
||||
map.Dock = DockStyle.Top;
|
||||
@@ -1698,6 +1889,7 @@ namespace MeshCentralRouter
|
||||
text += " \"meshId\": \"" + mapCtrl.node.meshid + "\",\r\n";
|
||||
text += " \"nodeId\": \"" + mapCtrl.node.nodeid + "\",\r\n";
|
||||
text += " \"appId\": " + mapCtrl.appId + ",\r\n";
|
||||
if (mapCtrl.appIdStr != null) { text += " \"appIdStr\": \"" + mapCtrl.appIdStr + "\",\r\n"; }
|
||||
text += " \"protocol\": " + map.protocol + ",\r\n";
|
||||
text += " \"localPort\": " + map.localport + ",\r\n";
|
||||
if (map.remoteip != null) { text += " \"remoteIP\": \"" + map.remoteip + "\",\r\n"; }
|
||||
@@ -1981,6 +2173,14 @@ namespace MeshCentralRouter
|
||||
if (form.ShowDialog(this) == DialogResult.OK) { }
|
||||
}
|
||||
|
||||
private void customAppsToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
CustomAppsForm f = new CustomAppsForm(Settings.GetApplications());
|
||||
if (f.ShowDialog(this) == DialogResult.OK) {
|
||||
Settings.SetApplications(f.getApplications());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private delegate void displayMessageHandler(string msg, int buttons, string extra, int progress);
|
||||
private void displayMessage(string msg, int buttons = 0, string extra = "", int progress = 0)
|
||||
|
||||
@@ -1473,6 +1473,12 @@
|
||||
<data name="settingsToolStripMenuItem.Text" xml:space="preserve">
|
||||
<value>S&ettings...</value>
|
||||
</data>
|
||||
<data name="customAppsToolStripMenuItem1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>185, 22</value>
|
||||
</data>
|
||||
<data name="customAppsToolStripMenuItem1.Text" xml:space="preserve">
|
||||
<value>&Custom Apps...</value>
|
||||
</data>
|
||||
<data name="mainContextMenuStrip.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>219, 146</value>
|
||||
</data>
|
||||
@@ -4348,6 +4354,12 @@ Click "Add" to get started.</value>
|
||||
<data name="settingsToolStripMenuItem1.Text" xml:space="preserve">
|
||||
<value>S&ettings...</value>
|
||||
</data>
|
||||
<data name="customAppsToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>168, 22</value>
|
||||
</data>
|
||||
<data name="customAppsToolStripMenuItem.Text" xml:space="preserve">
|
||||
<value>&Custom Apps...</value>
|
||||
</data>
|
||||
<data name="mappingsContextMenuStrip.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>194, 82</value>
|
||||
</data>
|
||||
@@ -6300,6 +6312,18 @@ Click "Add" to get started.</value>
|
||||
<data name=">>saveMapFileDialog.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.SaveFileDialog, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>customAppsToolStripMenuItem.Name" xml:space="preserve">
|
||||
<value>customAppsToolStripMenuItem</value>
|
||||
</data>
|
||||
<data name=">>customAppsToolStripMenuItem.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>customAppsToolStripMenuItem1.Name" xml:space="preserve">
|
||||
<value>customAppsToolStripMenuItem1</value>
|
||||
</data>
|
||||
<data name=">>customAppsToolStripMenuItem1.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>$this.Name" xml:space="preserve">
|
||||
<value>MainForm</value>
|
||||
</data>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -31,6 +31,7 @@ namespace MeshCentralRouter
|
||||
public string remoteIP = null;
|
||||
public int remotePort;
|
||||
public int appId;
|
||||
public string appIdStr;
|
||||
public NodeClass node;
|
||||
public MainForm parent;
|
||||
public MeshMapper mapper;
|
||||
@@ -72,7 +73,7 @@ namespace MeshCentralRouter
|
||||
public void Start()
|
||||
{
|
||||
routingStatusLabel.Text = Translate.T(Properties.Resources.Starting);
|
||||
appButton.Enabled = (appId != 0);
|
||||
appButton.Enabled = (appId != 0) || (appIdStr != null);
|
||||
mapper = new MeshMapper();
|
||||
mapper.xdebug = xdebug;
|
||||
mapper.inaddrany = inaddrany;
|
||||
@@ -110,7 +111,8 @@ namespace MeshCentralRouter
|
||||
if (protocol == 2) {
|
||||
statemsg = "UDP: " + statemsg;
|
||||
} else {
|
||||
if (appId == 1) { statemsg = "HTTP: " + statemsg; }
|
||||
if ((appId == 0) && (appIdStr != null)) { statemsg = appIdStr + ": " + statemsg; }
|
||||
else if (appId == 1) { statemsg = "HTTP: " + statemsg; }
|
||||
else if (appId == 2) { statemsg = "HTTPS: " + statemsg; }
|
||||
else if (appId == 3) { statemsg = "RDP: " + statemsg; }
|
||||
else if (appId == 4) { statemsg = "PuTTY: " + statemsg; }
|
||||
@@ -125,6 +127,23 @@ namespace MeshCentralRouter
|
||||
bool shift = false;
|
||||
if (Control.ModifierKeys == Keys.Shift) { shift = true; }
|
||||
|
||||
if (appId == 0)
|
||||
{
|
||||
if (appIdStr == null) return;
|
||||
string appCmd = null;
|
||||
string appArgs = null;
|
||||
List<String[]> apps = Settings.GetApplications();
|
||||
foreach (String[] app in apps) { if (app[1].ToLower() == appIdStr.ToLower()) { appCmd = app[2]; if (app[3] != null) { appArgs = app[3].Replace("%P", mapper.localport.ToString()).Replace("%L", "127.0.0.1").Replace("%N", "xxx"); } } }
|
||||
if (appCmd != null) {
|
||||
// Launch the process
|
||||
System.Diagnostics.Process proc = null;
|
||||
try { proc = System.Diagnostics.Process.Start(appCmd, appArgs); } catch (System.ComponentModel.Win32Exception) { }
|
||||
// Setup auto-exit
|
||||
if ((autoexit == true) && (parent.autoExitProc == null)) { parent.autoExitProc = proc; parent.SetAutoClose(); autoExitTimer.Enabled = true; }
|
||||
autoexit = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (appId == 1) { System.Diagnostics.Process.Start("http://localhost:" + mapper.localport); }
|
||||
if (appId == 2) { System.Diagnostics.Process.Start("https://localhost:" + mapper.localport); }
|
||||
if (appId == 3)
|
||||
@@ -153,6 +172,7 @@ namespace MeshCentralRouter
|
||||
|
||||
// Setup auto-exit
|
||||
if ((autoexit == true) && (parent.autoExitProc == null)) { parent.autoExitProc = proc; parent.SetAutoClose(); autoExitTimer.Enabled = true; }
|
||||
autoexit = false;
|
||||
}
|
||||
if (appId == 4)
|
||||
{
|
||||
@@ -179,6 +199,7 @@ namespace MeshCentralRouter
|
||||
|
||||
// Setup auto-exit
|
||||
if ((autoexit == true) && (parent.autoExitProc == null)) { parent.autoExitProc = proc; parent.SetAutoClose(); autoExitTimer.Enabled = true; }
|
||||
autoexit = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -209,6 +230,7 @@ namespace MeshCentralRouter
|
||||
|
||||
// Setup auto-exit
|
||||
if ((autoexit == true) && (parent.autoExitProc == null)) { parent.autoExitProc = proc; parent.SetAutoClose(); autoExitTimer.Enabled = true; }
|
||||
autoexit = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,6 +248,7 @@ namespace MeshCentralRouter
|
||||
|
||||
// Setup auto-exit
|
||||
if ((autoexit == true) && (parent.autoExitProc == null)) { parent.autoExitProc = proc; parent.SetAutoClose(); autoExitTimer.Enabled = true; }
|
||||
autoexit = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -246,6 +269,7 @@ namespace MeshCentralRouter
|
||||
|
||||
// Setup auto-exit
|
||||
if ((autoexit == true) && (parent.autoExitProc == null)) { parent.autoExitProc = proc; parent.SetAutoClose(); autoExitTimer.Enabled = true; }
|
||||
autoexit = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>MeshCentralRouter</RootNamespace>
|
||||
<AssemblyName>MeshCentralRouter</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<StartupObject>MeshCentralRouter.Program</StartupObject>
|
||||
<ApplicationIcon>MeshServer.ico</ApplicationIcon>
|
||||
@@ -94,6 +94,24 @@
|
||||
<Compile Include="AddRelayMapForm.designer.cs">
|
||||
<DependentUpon>AddRelayMapForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="CustomAppsAddForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="CustomAppsAddForm.Designer.cs">
|
||||
<DependentUpon>CustomAppsAddForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="CustomAppsForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="CustomAppsForm.Designer.cs">
|
||||
<DependentUpon>CustomAppsForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="CustomAppsRunForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="CustomAppsRunForm.Designer.cs">
|
||||
<DependentUpon>CustomAppsRunForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="FileConfirmOverwriteForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@@ -111,6 +129,14 @@
|
||||
</Compile>
|
||||
<Compile Include="ProxySettings.Designer.cs">
|
||||
<DependentUpon>ProxySettings.cs</DependentUpon>
|
||||
<Compile Include="ListViewExtended.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="KVMViewerExtra.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="KVMViewerExtra.Designer.cs">
|
||||
<DependentUpon>KVMViewerExtra.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="LocalPipe.cs" />
|
||||
<Compile Include="SshUsernameForm.cs">
|
||||
@@ -274,6 +300,15 @@
|
||||
<EmbeddedResource Include="AddRelayMapForm.resx">
|
||||
<DependentUpon>AddRelayMapForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="CustomAppsAddForm.resx">
|
||||
<DependentUpon>CustomAppsAddForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="CustomAppsForm.resx">
|
||||
<DependentUpon>CustomAppsForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="CustomAppsRunForm.resx">
|
||||
<DependentUpon>CustomAppsRunForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="FileConfirmOverwriteForm.resx">
|
||||
<DependentUpon>FileConfirmOverwriteForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
@@ -283,6 +318,9 @@
|
||||
<EmbeddedResource Include="ProxySettings.resx">
|
||||
<DependentUpon>ProxySettings.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="KVMViewerExtra.resx">
|
||||
<DependentUpon>KVMViewerExtra.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="SshUsernameForm.resx">
|
||||
<DependentUpon>SshUsernameForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
@@ -376,6 +414,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="MeshServer.ico" />
|
||||
<None Include="Resources\icon-monitor1.png" />
|
||||
<None Include="Resources\folderzip.png" />
|
||||
<None Include="Resources\arrowleft16.png" />
|
||||
<None Include="Resources\arrowright16.png" />
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -50,8 +50,6 @@ namespace MeshCentralRouter
|
||||
public delegate void onStateMsgChangedHandler(string statemsg);
|
||||
public event onStateMsgChangedHandler onStateMsgChanged;
|
||||
|
||||
|
||||
|
||||
// Starts the routing server, called when the start button is pressed
|
||||
public void start(MeshCentralServer parent, int protocol, int localPort, string url, int remotePort, string remoteIP)
|
||||
{
|
||||
@@ -192,7 +190,6 @@ namespace MeshCentralRouter
|
||||
Uri wsurl = new Uri(url + "&auth=" + Uri.EscapeDataString(parent.authCookie));
|
||||
Debug("#" + counter + ": Connecting web socket to: " + wsurl.ToString());
|
||||
wc.debug = xdebug;
|
||||
wc.Start(wsurl, certhash);
|
||||
wc.tag = client;
|
||||
wc.id = counter;
|
||||
wc.tunneling = false;
|
||||
@@ -200,6 +197,8 @@ namespace MeshCentralRouter
|
||||
wc.onBinaryData += Wc_onBinaryData;
|
||||
wc.onStringData += Wc_onStringData;
|
||||
wc.onSendOk += Wc_onSendOk;
|
||||
wc.TLSCertCheck = webSocketClient.TLSCertificateCheck.Fingerprint;
|
||||
wc.Start(wsurl, certhash, null);
|
||||
}
|
||||
|
||||
private void ConnectWS(UdpClient client, int counter)
|
||||
@@ -208,7 +207,6 @@ namespace MeshCentralRouter
|
||||
Uri wsurl = new Uri(url + "&auth=" + Uri.EscapeDataString(parent.authCookie));
|
||||
Debug("#" + counter + ": Connecting web socket to: " + wsurl.ToString());
|
||||
wc.debug = xdebug;
|
||||
wc.Start(wsurl, certhash);
|
||||
wc.tag = client;
|
||||
wc.id = counter;
|
||||
wc.tunneling = false;
|
||||
@@ -216,6 +214,8 @@ namespace MeshCentralRouter
|
||||
wc.onBinaryData += Wc_onBinaryData;
|
||||
wc.onStringData += Wc_onStringData;
|
||||
wc.onSendOk += Wc_onSendOk;
|
||||
wc.TLSCertCheck = webSocketClient.TLSCertificateCheck.Fingerprint;
|
||||
wc.Start(wsurl, certhash, null);
|
||||
}
|
||||
|
||||
private void Wc_onSendOk(webSocketClient sender)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
28
Properties/Resources.Designer.cs
generated
28
Properties/Resources.Designer.cs
generated
@@ -424,6 +424,16 @@ namespace MeshCentralRouter.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap icon_monitor1 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("icon-monitor1", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
@@ -481,6 +491,15 @@ namespace MeshCentralRouter.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Join.
|
||||
/// </summary>
|
||||
internal static string Join {
|
||||
get {
|
||||
return ResourceManager.GetString("Join", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Changing language will close this tool. Are you sure?.
|
||||
/// </summary>
|
||||
@@ -835,6 +854,15 @@ namespace MeshCentralRouter.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Split.
|
||||
/// </summary>
|
||||
internal static string Split {
|
||||
get {
|
||||
return ResourceManager.GetString("Split", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Starting....
|
||||
/// </summary>
|
||||
|
||||
@@ -120,21 +120,18 @@
|
||||
<data name="CIRA" xml:space="preserve">
|
||||
<value>CIRA</value>
|
||||
</data>
|
||||
<data name="ToggleRemoteDesktopConnection" xml:space="preserve">
|
||||
<value>Toggle remote desktop connection</value>
|
||||
</data>
|
||||
<data name="UnableToOpenFileX" xml:space="preserve">
|
||||
<value>Unable to open file: {0}</value>
|
||||
<data name="ChangeRemoteDesktopSettings" xml:space="preserve">
|
||||
<value>Change remote desktop settings</value>
|
||||
</data>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="MeshCentral" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MeshCentral.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<data name="Gear20" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Gear20.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="Connect" xml:space="preserve">
|
||||
<value>Connect</value>
|
||||
<data name="iconClipboardIn" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\icon-clipboard-in.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="XBytes" xml:space="preserve">
|
||||
<value>{0} Bytes</value>
|
||||
<data name="ZipSelectedFiles" xml:space="preserve">
|
||||
<value>ZIP Selected Files</value>
|
||||
</data>
|
||||
<data name="Denied" xml:space="preserve">
|
||||
<value>Denied</value>
|
||||
@@ -142,12 +139,6 @@
|
||||
<data name="InvalidUsernameOrPassword" xml:space="preserve">
|
||||
<value>Invalid username or password</value>
|
||||
</data>
|
||||
<data name="XbytesPersec" xml:space="preserve">
|
||||
<value>{0} bytes/sec</value>
|
||||
</data>
|
||||
<data name="Slow" xml:space="preserve">
|
||||
<value>Slow</value>
|
||||
</data>
|
||||
<data name="DisplayConnectionStatistics" xml:space="preserve">
|
||||
<value>Display connection statistics</value>
|
||||
</data>
|
||||
@@ -157,14 +148,14 @@
|
||||
<data name="Computer50" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\50-Computer.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="Almostdone" xml:space="preserve">
|
||||
<value>Almost done</value>
|
||||
</data>
|
||||
<data name="EmailSent" xml:space="preserve">
|
||||
<value>Email sent</value>
|
||||
</data>
|
||||
<data name="PortXtoIPPortY" xml:space="preserve">
|
||||
<value>Port {0} to {1}:{2}</value>
|
||||
</data>
|
||||
<data name="xminutesleft" xml:space="preserve">
|
||||
<value>{0} minutes left</value>
|
||||
<data name="Rename" xml:space="preserve">
|
||||
<value>Rename</value>
|
||||
</data>
|
||||
<data name="FailedToStartRemoteTerminalSession" xml:space="preserve">
|
||||
<value>Failed to start remote terminal session</value>
|
||||
@@ -175,8 +166,8 @@
|
||||
<data name="EmptyBanner" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Empty-Banner.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="PuttyAppName" xml:space="preserve">
|
||||
<value>PuTTY SSH client</value>
|
||||
<data name="ReceivedInvalidNetworkData" xml:space="preserve">
|
||||
<value>Received invalid network data</value>
|
||||
</data>
|
||||
<data name="XMbytesPersec" xml:space="preserve">
|
||||
<value>{0} Mbytes/sec</value>
|
||||
@@ -184,8 +175,8 @@
|
||||
<data name="refresh16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\refresh16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="NoToolsAllowed" xml:space="preserve">
|
||||
<value>No tools allowed</value>
|
||||
<data name="delete16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\delete16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="SendCtrlAltDelToRemoteDevice" xml:space="preserve">
|
||||
<value>Send Ctrl-Alt-Del to remote device</value>
|
||||
@@ -193,20 +184,23 @@
|
||||
<data name="Fast" xml:space="preserve">
|
||||
<value>Fast</value>
|
||||
</data>
|
||||
<data name="xsecondsleft" xml:space="preserve">
|
||||
<value>{0} seconds left</value>
|
||||
<data name="RecordedSession" xml:space="preserve">
|
||||
<value>, Recorded Session</value>
|
||||
</data>
|
||||
<data name="SearchPlaceHolder" xml:space="preserve">
|
||||
<value>Search</value>
|
||||
</data>
|
||||
<data name="OverwriteOneFile" xml:space="preserve">
|
||||
<value>Overwrite 1 file?</value>
|
||||
<data name="SendTokenEmail" xml:space="preserve">
|
||||
<value>Send token to registered email address?</value>
|
||||
</data>
|
||||
<data name="DontAskXDays" xml:space="preserve">
|
||||
<value>Don't ask for {0} days.</value>
|
||||
</data>
|
||||
<data name="Rename" xml:space="preserve">
|
||||
<value>Rename</value>
|
||||
<data name="Stopped2" xml:space="preserve">
|
||||
<value>Stopped</value>
|
||||
</data>
|
||||
<data name="MeshCentral" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MeshCentral.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="Connecting" xml:space="preserve">
|
||||
<value>Connecting...</value>
|
||||
@@ -214,11 +208,14 @@
|
||||
<data name="MeshCentralTitle" xml:space="preserve">
|
||||
<value>MeshCentral</value>
|
||||
</data>
|
||||
<data name="folderzip" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\folderzip.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="FailedToStartRemoteDesktopSession" xml:space="preserve">
|
||||
<value>Failed to start remote desktop session</value>
|
||||
</data>
|
||||
<data name="ReceivedInvalidNetworkData" xml:space="preserve">
|
||||
<value>Received invalid network data</value>
|
||||
<data name="Offline" xml:space="preserve">
|
||||
<value>Offline</value>
|
||||
</data>
|
||||
<data name="EmailVerificationRequired" xml:space="preserve">
|
||||
<value>Email verification required</value>
|
||||
@@ -229,20 +226,20 @@
|
||||
<data name="UnableToWriteFileX" xml:space="preserve">
|
||||
<value>Unable to write file: {0}</value>
|
||||
</data>
|
||||
<data name="WinscpAppName" xml:space="preserve">
|
||||
<value>WinSCP client</value>
|
||||
</data>
|
||||
<data name="XKbytesPersec" xml:space="preserve">
|
||||
<value>{0} Kbytes/sec</value>
|
||||
</data>
|
||||
<data name="LanguagesChanging" xml:space="preserve">
|
||||
<value>Changing language will close this tool. Are you sure?</value>
|
||||
</data>
|
||||
<data name="InvalidDownload" xml:space="preserve">
|
||||
<value>Invalid download.</value>
|
||||
<data name="Connected" xml:space="preserve">
|
||||
<value>Connected</value>
|
||||
</data>
|
||||
<data name="RemoveXItems" xml:space="preserve">
|
||||
<value>Remove {0} items?</value>
|
||||
</data>
|
||||
<data name="ChangeRemoteDesktopSettings" xml:space="preserve">
|
||||
<value>Change remote desktop settings</value>
|
||||
<data name="Close" xml:space="preserve">
|
||||
<value>Close</value>
|
||||
</data>
|
||||
<data name="SendTokenSMS" xml:space="preserve">
|
||||
<value>Send token to registered phone number?</value>
|
||||
@@ -256,17 +253,20 @@
|
||||
<data name="PushLocaClipboardToRemoteDevice" xml:space="preserve">
|
||||
<value>Push local clipboard to remote device</value>
|
||||
</data>
|
||||
<data name="UnableToBindToLocalPort" xml:space="preserve">
|
||||
<value>Unable to bind to local port</value>
|
||||
<data name="xminutesleft" xml:space="preserve">
|
||||
<value>{0} minutes left</value>
|
||||
</data>
|
||||
<data name="iconClipboardIn" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\icon-clipboard-in.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<data name="ToggleRemoteDesktopConnection" xml:space="preserve">
|
||||
<value>Toggle remote desktop connection</value>
|
||||
</data>
|
||||
<data name="MC2Banner" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MC2-Banner.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<data name="Local" xml:space="preserve">
|
||||
<value>Local</value>
|
||||
</data>
|
||||
<data name="ErrorUploadingFileX" xml:space="preserve">
|
||||
<value>Error uploading file: {0}</value>
|
||||
<data name="Join" xml:space="preserve">
|
||||
<value>Join</value>
|
||||
</data>
|
||||
<data name="Relay" xml:space="preserve">
|
||||
<value>Relay</value>
|
||||
</data>
|
||||
<data name="Disconnected" xml:space="preserve">
|
||||
<value>Disconnected</value>
|
||||
@@ -280,8 +280,8 @@
|
||||
<data name="Medium" xml:space="preserve">
|
||||
<value>Medium</value>
|
||||
</data>
|
||||
<data name="RemotePlus" xml:space="preserve">
|
||||
<value>Remote - {0}</value>
|
||||
<data name="PuttyAppName" xml:space="preserve">
|
||||
<value>PuTTY SSH client</value>
|
||||
</data>
|
||||
<data name="PullClipboardFromRemoteDevice" xml:space="preserve">
|
||||
<value>Pull clipboard from remote device</value>
|
||||
@@ -295,26 +295,23 @@
|
||||
<data name="PortXtoPortY" xml:space="preserve">
|
||||
<value>Port {0} to port {1}</value>
|
||||
</data>
|
||||
<data name="VerySlow" xml:space="preserve">
|
||||
<value>Very slow</value>
|
||||
</data>
|
||||
<data name="Remove1Item" xml:space="preserve">
|
||||
<value>Remove 1 item?</value>
|
||||
</data>
|
||||
<data name="ManyConnections" xml:space="preserve">
|
||||
<value>, {0} connections.</value>
|
||||
<data name="OverwriteOneFile" xml:space="preserve">
|
||||
<value>Overwrite 1 file?</value>
|
||||
</data>
|
||||
<data name="IndividualDevices" xml:space="preserve">
|
||||
<value>(Individual Devices)</value>
|
||||
</data>
|
||||
<data name="xinstall" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\xinstall.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<data name="Split" xml:space="preserve">
|
||||
<value>Split</value>
|
||||
</data>
|
||||
<data name="CreateFolder" xml:space="preserve">
|
||||
<value>Create Folder</value>
|
||||
</data>
|
||||
<data name="arrowright16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\arrowright16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<data name="XBytes" xml:space="preserve">
|
||||
<value>{0} Bytes</value>
|
||||
</data>
|
||||
<data name="Updating" xml:space="preserve">
|
||||
<value>Updating...</value>
|
||||
@@ -334,8 +331,8 @@
|
||||
<data name="xhoursleft" xml:space="preserve">
|
||||
<value>{0} hours left</value>
|
||||
</data>
|
||||
<data name="iconClipboardOut" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\icon-clipboard-out.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<data name="InvalidDownload" xml:space="preserve">
|
||||
<value>Invalid download.</value>
|
||||
</data>
|
||||
<data name="WaitingForUserToGrantAccess" xml:space="preserve">
|
||||
<value>Waiting for user to grant access...</value>
|
||||
@@ -346,26 +343,29 @@
|
||||
<data name="AllDisplays" xml:space="preserve">
|
||||
<value>All Displays</value>
|
||||
</data>
|
||||
<data name="HelpRelayMap" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\HelpRelayMap.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<data name="xsecondsleft" xml:space="preserve">
|
||||
<value>{0} seconds left</value>
|
||||
</data>
|
||||
<data name="MeshCentralRouter" xml:space="preserve">
|
||||
<value>MeshCentral Router</value>
|
||||
<data name="xinstall" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\xinstall.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="Disconnect" xml:space="preserve">
|
||||
<value>Disconnect</value>
|
||||
</data>
|
||||
<data name="AMT" xml:space="preserve">
|
||||
<value>AMT</value>
|
||||
</data>
|
||||
<data name="Local" xml:space="preserve">
|
||||
<value>Local</value>
|
||||
<data name="PortXtoIPPortY" xml:space="preserve">
|
||||
<value>Port {0} to {1}:{2}</value>
|
||||
</data>
|
||||
<data name="Relay" xml:space="preserve">
|
||||
<value>Relay</value>
|
||||
<data name="ErrorUploadingFileX" xml:space="preserve">
|
||||
<value>Error uploading file: {0}</value>
|
||||
</data>
|
||||
<data name="icons01" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\icons01.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="UnableToConnect" xml:space="preserve">
|
||||
<value>Unable to connect</value>
|
||||
<data name="RemoveXItems" xml:space="preserve">
|
||||
<value>Remove {0} items?</value>
|
||||
</data>
|
||||
<data name="Setup" xml:space="preserve">
|
||||
<value>Setup...</value>
|
||||
@@ -376,14 +376,17 @@
|
||||
<data name="arrowleft16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\arrowleft16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="Close" xml:space="preserve">
|
||||
<value>Close</value>
|
||||
<data name="UnableToConnect" xml:space="preserve">
|
||||
<value>Unable to connect</value>
|
||||
</data>
|
||||
<data name="AddXUsers" xml:space="preserve">
|
||||
<value>, {0} users</value>
|
||||
<data name="UnableToBindToLocalPort" xml:space="preserve">
|
||||
<value>Unable to bind to local port</value>
|
||||
</data>
|
||||
<data name="Disconnect" xml:space="preserve">
|
||||
<value>Disconnect</value>
|
||||
<data name="NoToolsAllowed" xml:space="preserve">
|
||||
<value>No tools allowed</value>
|
||||
</data>
|
||||
<data name="arrowright16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\arrowright16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="LanguagesTitle" xml:space="preserve">
|
||||
<value>Languages</value>
|
||||
@@ -391,14 +394,17 @@
|
||||
<data name="LocalPlus" xml:space="preserve">
|
||||
<value>Local - {0}</value>
|
||||
</data>
|
||||
<data name="Gear20" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Gear20.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<data name="XbytesPersec" xml:space="preserve">
|
||||
<value>{0} bytes/sec</value>
|
||||
</data>
|
||||
<data name="Offline" xml:space="preserve">
|
||||
<value>Offline</value>
|
||||
<data name="iconClipboardOut" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\icon-clipboard-out.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="RecordedSession" xml:space="preserve">
|
||||
<value>, Recorded Session</value>
|
||||
<data name="VerySlow" xml:space="preserve">
|
||||
<value>Very slow</value>
|
||||
</data>
|
||||
<data name="MeshCentralRouter" xml:space="preserve">
|
||||
<value>MeshCentral Router</value>
|
||||
</data>
|
||||
<data name="OneByte" xml:space="preserve">
|
||||
<value>{0} Byte</value>
|
||||
@@ -409,43 +415,46 @@
|
||||
<data name="folderup16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\folderup16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="delete16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\delete16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<data name="UnableToOpenFileX" xml:space="preserve">
|
||||
<value>Unable to open file: {0}</value>
|
||||
</data>
|
||||
<data name="WinscpAppName" xml:space="preserve">
|
||||
<value>WinSCP client</value>
|
||||
<data name="MC2Banner" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MC2-Banner.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="OneConnection" xml:space="preserve">
|
||||
<value>, 1 connection.</value>
|
||||
</data>
|
||||
<data name="Connect" xml:space="preserve">
|
||||
<value>Connect</value>
|
||||
</data>
|
||||
<data name="TwoFactorAuthentication" xml:space="preserve">
|
||||
<value>Two-factor Authentication</value>
|
||||
</data>
|
||||
<data name="Agent" xml:space="preserve">
|
||||
<value>Agent</value>
|
||||
</data>
|
||||
<data name="Connected" xml:space="preserve">
|
||||
<value>Connected</value>
|
||||
<data name="ManyConnections" xml:space="preserve">
|
||||
<value>, {0} connections.</value>
|
||||
</data>
|
||||
<data name="RemotePlus" xml:space="preserve">
|
||||
<value>Remote - {0}</value>
|
||||
</data>
|
||||
<data name="ErrorDownloadingFileX" xml:space="preserve">
|
||||
<value>Error downloading file: {0}</value>
|
||||
</data>
|
||||
<data name="Almostdone" xml:space="preserve">
|
||||
<value>Almost done</value>
|
||||
<data name="HelpRelayMap" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\HelpRelayMap.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="Remote" xml:space="preserve">
|
||||
<value>Remote</value>
|
||||
</data>
|
||||
<data name="SendTokenEmail" xml:space="preserve">
|
||||
<value>Send token to registered email address?</value>
|
||||
<data name="Slow" xml:space="preserve">
|
||||
<value>Slow</value>
|
||||
</data>
|
||||
<data name="Stopped2" xml:space="preserve">
|
||||
<value>Stopped</value>
|
||||
<data name="AddXUsers" xml:space="preserve">
|
||||
<value>, {0} users</value>
|
||||
</data>
|
||||
<data name="folderzip" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\folderzip.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="ZipSelectedFiles" xml:space="preserve">
|
||||
<value>ZIP Selected Files</value>
|
||||
<data name="icon-monitor1" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\icon-monitor1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
||||
BIN
Resources/icon-monitor1.png
Normal file
BIN
Resources/icon-monitor1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 396 B |
BIN
Resources/icon-monitor1b.png
Normal file
BIN
Resources/icon-monitor1b.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 339 B |
BIN
Resources/icon-monitor2.png
Normal file
BIN
Resources/icon-monitor2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 461 B |
BIN
Resources/icon-monitor2b.png
Normal file
BIN
Resources/icon-monitor2b.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 409 B |
BIN
Resources/monitor32.png
Normal file
BIN
Resources/monitor32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 848 B |
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
58
Settings.cs
58
Settings.cs
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
using Microsoft.Win32;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace MeshCentralRouter
|
||||
@@ -37,7 +38,11 @@ namespace MeshCentralRouter
|
||||
/// <returns></returns>
|
||||
public static string GetRegValue(string name, string value)
|
||||
{
|
||||
try { return Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\Open Source\MeshCentral Router", name, value).ToString(); } catch (Exception) { return value; }
|
||||
try {
|
||||
String v = (String)Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\Open Source\MeshCentral Router", name, value);
|
||||
if (v == null) return value;
|
||||
return v.ToString();
|
||||
} catch (Exception) { return value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// This function querys the registry. If the key is found it returns the value as a boolean
|
||||
@@ -49,5 +54,54 @@ namespace MeshCentralRouter
|
||||
{
|
||||
try { return bool.Parse(GetRegValue(name, value.ToString())); } catch (Exception) { return value; }
|
||||
}
|
||||
|
||||
public static void SetApplications(List<string[]> apps)
|
||||
{
|
||||
ClearApplications();
|
||||
using (RegistryKey key = Registry.CurrentUser.CreateSubKey(@"HKEY_CURRENT_USER\SOFTWARE\Open Source\MeshCentral Router\Applications", true))
|
||||
{
|
||||
foreach (string[] app in apps)
|
||||
{
|
||||
using (RegistryKey skey = key.CreateSubKey(app[0]))
|
||||
{
|
||||
skey.SetValue("Protocol", app[1]);
|
||||
skey.SetValue("Command", app[2]);
|
||||
skey.SetValue("Arguments", app[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<string[]> GetApplications()
|
||||
{
|
||||
List<string[]> apps = new List<string[]>();
|
||||
using (RegistryKey key = Registry.CurrentUser.CreateSubKey(@"HKEY_CURRENT_USER\SOFTWARE\Open Source\MeshCentral Router\Applications\", false))
|
||||
{
|
||||
string[] keys = key.GetSubKeyNames();
|
||||
foreach (string k in keys)
|
||||
{
|
||||
using (RegistryKey key2 = Registry.CurrentUser.OpenSubKey(@"HKEY_CURRENT_USER\SOFTWARE\Open Source\MeshCentral Router\Applications\" + k, false))
|
||||
{
|
||||
string protocol = (string)key2.GetValue("Protocol");
|
||||
string command = (string)key2.GetValue("Command");
|
||||
string args = (string)key2.GetValue("Arguments");
|
||||
String[] a = new string[4];
|
||||
a[0] = k;
|
||||
a[1] = protocol;
|
||||
a[2] = command;
|
||||
a[3] = args;
|
||||
apps.Add(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
return apps;
|
||||
}
|
||||
|
||||
public static void ClearApplications()
|
||||
{
|
||||
RegistryKey key = Registry.CurrentUser.CreateSubKey(@"HKEY_CURRENT_USER\SOFTWARE\Open Source\MeshCentral Router", true);
|
||||
key.DeleteSubKeyTree("Applications");
|
||||
key.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
7431
Translate.cs
7431
Translate.cs
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -18,9 +18,12 @@ using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Net.Sockets;
|
||||
using System.Net.Security;
|
||||
using System.Net.WebSockets;
|
||||
using System.IO.Compression;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
@@ -30,6 +33,9 @@ namespace MeshCentralRouter
|
||||
{
|
||||
public class webSocketClient : IDisposable
|
||||
{
|
||||
private ClientWebSocket ws = null; // Native Windows WebSocket
|
||||
private CancellationTokenSource CTS;
|
||||
|
||||
public bool AllowCompression = true;
|
||||
private TcpClient wsclient = null;
|
||||
private SslStream wsstream = null;
|
||||
@@ -45,10 +51,11 @@ namespace MeshCentralRouter
|
||||
private bool proxyInUse = false;
|
||||
private Uri proxyUri = null;
|
||||
private string tlsCertFingerprint = null;
|
||||
private string tlsCertFingerprint2 = null;
|
||||
//private ConnectionErrors lastError = ConnectionErrors.NoError;
|
||||
public bool debug = false;
|
||||
public bool xignoreCert = false;
|
||||
public string extraHeaders = null;
|
||||
public bool tlsdump = false;
|
||||
public Dictionary<string, string> extraHeaders = null;
|
||||
private MemoryStream inflateMemory;
|
||||
private DeflateStream inflate;
|
||||
private MemoryStream deflateMemory;
|
||||
@@ -58,13 +65,18 @@ namespace MeshCentralRouter
|
||||
public int pongTimeSeconds = 0;
|
||||
private System.Threading.Timer pingTimer = null;
|
||||
private System.Threading.Timer pongTimer = null;
|
||||
private System.Threading.Timer connectTimer = null;
|
||||
private bool pendingSendCall = false;
|
||||
private MemoryStream pendingSendBuffer = null;
|
||||
public long PendingSendLength { get { return (pendingSendBuffer == null)? 0 : pendingSendBuffer.Length; } }
|
||||
private bool readPaused = false;
|
||||
private bool shouldRead = false;
|
||||
private RNGCryptoServiceProvider CryptoRandom = new RNGCryptoServiceProvider();
|
||||
private object mainLock = new object();
|
||||
public TLSCertificateCheck TLSCertCheck = TLSCertificateCheck.Verify;
|
||||
public X509Certificate2 tlsCert = null;
|
||||
public X509Certificate2 failedTlsCert = null;
|
||||
static public bool nativeWebSocketFirst = false;
|
||||
private SemaphoreSlim receiveLock = new SemaphoreSlim(1, 1);
|
||||
|
||||
// Outside variables
|
||||
public object tag = null;
|
||||
@@ -80,11 +92,22 @@ namespace MeshCentralRouter
|
||||
Connected = 2
|
||||
}
|
||||
|
||||
public enum TLSCertificateCheck
|
||||
{
|
||||
Ignore = 0,
|
||||
Fingerprint = 1,
|
||||
Verify = 2
|
||||
}
|
||||
|
||||
public enum ConnectionErrors
|
||||
{
|
||||
NoError = 0
|
||||
}
|
||||
|
||||
public long PendingSendLength { get { if (ws != null) { lock (pendingSends) { return pendingSends.Count; } } else { return (pendingSendBuffer == null) ? 0 : pendingSendBuffer.Length; } } }
|
||||
|
||||
private void TlsDump(string direction, byte[] data, int offset, int len) { if (tlsdump) { try { File.AppendAllText("debug.log", direction + ": " + BitConverter.ToString(data, offset, len).Replace("-", string.Empty) + "\r\n"); } catch (Exception) { } } }
|
||||
|
||||
public delegate void onBinaryDataHandler(webSocketClient sender, byte[] data, int offset, int length, int orglen);
|
||||
public event onBinaryDataHandler onBinaryData;
|
||||
public delegate void onStringDataHandler(webSocketClient sender, string data, int orglen);
|
||||
@@ -98,12 +121,7 @@ namespace MeshCentralRouter
|
||||
|
||||
public ConnectionStates State { get { return state; } }
|
||||
|
||||
public X509Certificate RemoteCertificate {
|
||||
get
|
||||
{
|
||||
try { return wsstream.RemoteCertificate; } catch (Exception) { return null; }
|
||||
}
|
||||
}
|
||||
public X509Certificate RemoteCertificate { get { if (tlsCert != null) return tlsCert; try { return wsstream.RemoteCertificate; } catch (Exception) { return null; } } }
|
||||
|
||||
private void SetState(ConnectionStates newstate)
|
||||
{
|
||||
@@ -114,8 +132,20 @@ namespace MeshCentralRouter
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (ws != null)
|
||||
{
|
||||
if (ws.State == WebSocketState.Open)
|
||||
{
|
||||
CTS.CancelAfter(TimeSpan.FromSeconds(2));
|
||||
ws.CloseOutputAsync(WebSocketCloseStatus.Empty, "", CancellationToken.None);
|
||||
ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
|
||||
}
|
||||
try { if (ws != null) { ws.Dispose(); ws = null; } } catch (Exception) { }
|
||||
try { if (CTS != null) { CTS.Dispose(); CTS = null; } } catch (Exception) { }
|
||||
}
|
||||
if (pingTimer != null) { pingTimer.Dispose(); pingTimer = null; }
|
||||
if (pongTimer != null) { pongTimer.Dispose(); pongTimer = null; }
|
||||
if (connectTimer != null) { try { connectTimer.Dispose(); } catch (Exception) { } connectTimer = null; }
|
||||
if (wsstream != null) { try { wsstream.Close(); } catch (Exception) { } try { wsstream.Dispose(); } catch (Exception) { } wsstream = null; }
|
||||
if (wsclient != null) { wsclient = null; }
|
||||
if (pendingSendBuffer != null) { pendingSendBuffer.Dispose(); pendingSendBuffer = null; }
|
||||
@@ -129,42 +159,108 @@ namespace MeshCentralRouter
|
||||
if (debug) { try { File.AppendAllText("debug.log", DateTime.Now.ToString("HH:mm:tt.ffff") + ": WebSocket: " + msg + "\r\n"); } catch (Exception) { } }
|
||||
}
|
||||
|
||||
public bool Start(Uri url, string tlsCertFingerprint)
|
||||
private async Task ConnectAsync(Uri url)
|
||||
{
|
||||
if (state != ConnectionStates.Disconnected) return false;
|
||||
SetState(ConnectionStates.Connecting);
|
||||
this.url = url;
|
||||
if (tlsCertFingerprint != null) { this.tlsCertFingerprint = tlsCertFingerprint.ToUpper(); }
|
||||
|
||||
|
||||
Log("Websocket Start, URL=" + ((url == null) ? "(NULL)" : url.ToString()));
|
||||
|
||||
proxyUri = Win32Api.GetProxy(url);
|
||||
if (CTS != null) CTS.Dispose();
|
||||
CTS = new CancellationTokenSource();
|
||||
try { await ws.ConnectAsync(url, CTS.Token); } catch (Exception) { SetState(0); return; }
|
||||
await Task.Factory.StartNew(ReceiveLoop, CTS.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
||||
}
|
||||
|
||||
if (proxyUri != null)
|
||||
public async Task DisconnectAsync()
|
||||
{
|
||||
if (ws == null) return;
|
||||
if (ws.State == WebSocketState.Open)
|
||||
{
|
||||
// Proxy in use
|
||||
Log("Websocket proxyUri: " + proxyUri.ToString());
|
||||
proxyInUse = true;
|
||||
wsclient = new TcpClient();
|
||||
wsclient.BeginConnect(proxyUri.Host, proxyUri.Port, new AsyncCallback(OnConnectSink), this);
|
||||
CTS.CancelAfter(TimeSpan.FromSeconds(2));
|
||||
await ws.CloseOutputAsync(WebSocketCloseStatus.Empty, "", CancellationToken.None);
|
||||
await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
|
||||
}
|
||||
ws.Dispose();
|
||||
ws = null;
|
||||
CTS.Dispose();
|
||||
CTS = null;
|
||||
}
|
||||
|
||||
public bool Start(Uri url, string tlsCertFingerprint, string tlsCertFingerprint2, bool force = false)
|
||||
{
|
||||
if ((force == false) && (state != ConnectionStates.Disconnected)) return false;
|
||||
SetState(ConnectionStates.Connecting);
|
||||
this.url = url;
|
||||
if (tlsCertFingerprint != null) { this.tlsCertFingerprint = tlsCertFingerprint.ToUpper(); }
|
||||
if (tlsCertFingerprint2 != null) { this.tlsCertFingerprint2 = tlsCertFingerprint2.ToUpper(); }
|
||||
if (nativeWebSocketFirst) { try { ws = new ClientWebSocket(); } catch (Exception) { } }
|
||||
if (ws != null)
|
||||
{
|
||||
// Use Windows native websockets
|
||||
Log("Websocket (native) Start, URL=" + ((url == null) ? "(NULL)" : url.ToString()));
|
||||
if (extraHeaders != null) { foreach (var key in extraHeaders.Keys) { ws.Options.SetRequestHeader(key, extraHeaders[key]); } }
|
||||
Task t = ConnectAsync(url);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No proxy in use
|
||||
Log("Websocket noProxy");
|
||||
proxyInUse = false;
|
||||
wsclient = new TcpClient();
|
||||
string h = url.Host;
|
||||
if (h.StartsWith("[") && h.EndsWith("]")) { h = h.Substring(1, h.Length - 2); }
|
||||
wsclient.BeginConnect(h, url.Port, new AsyncCallback(OnConnectSink), this);
|
||||
}
|
||||
// Use C# coded websockets
|
||||
Uri proxyUri = null;
|
||||
Log("Websocket Start, URL=" + ((url == null) ? "(NULL)" : url.ToString()));
|
||||
|
||||
// Check if we need to use a HTTP proxy (Auto-proxy way)
|
||||
try
|
||||
{
|
||||
RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
|
||||
Object x = registryKey.GetValue("AutoConfigURL", null);
|
||||
if ((x != null) && (x.GetType() == typeof(string)))
|
||||
{
|
||||
string proxyStr = GetProxyForUrlUsingPac("http" + ((url.Port == 80) ? "" : "s") + "://" + url.Host + ":" + url.Port, x.ToString());
|
||||
if (proxyStr != null) { proxyUri = new Uri("http://" + proxyStr); }
|
||||
}
|
||||
}
|
||||
catch (Exception) { proxyUri = null; }
|
||||
|
||||
// Check if we need to use a HTTP proxy (Normal way)
|
||||
if (proxyUri == null)
|
||||
{
|
||||
var proxy = System.Net.HttpWebRequest.GetSystemWebProxy();
|
||||
proxyUri = proxy.GetProxy(url);
|
||||
if ((url.Host.ToLower() == proxyUri.Host.ToLower()) && (url.Port == proxyUri.Port)) { proxyUri = null; }
|
||||
}
|
||||
|
||||
if (proxyUri != null)
|
||||
{
|
||||
// Proxy in use
|
||||
Log("Websocket proxyUri: " + proxyUri.ToString());
|
||||
proxyInUse = true;
|
||||
wsclient = new TcpClient();
|
||||
wsclient.BeginConnect(proxyUri.Host, proxyUri.Port, new AsyncCallback(OnConnectSink), this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No proxy in use
|
||||
Log("Websocket noProxy");
|
||||
proxyInUse = false;
|
||||
wsclient = new TcpClient();
|
||||
string h = url.Host;
|
||||
if (h.StartsWith("[") && h.EndsWith("]")) { h = h.Substring(1, h.Length - 2); }
|
||||
wsclient.BeginConnect(h, url.Port, new AsyncCallback(OnConnectSink), this);
|
||||
}
|
||||
|
||||
// Start a timer that will fallback to native sockets automatically.
|
||||
// For some proxy types, native websockets are the only way to connect.
|
||||
if (connectTimer != null) { try { connectTimer.Dispose(); } catch (Exception) { } connectTimer = null; }
|
||||
connectTimer = new System.Threading.Timer(new System.Threading.TimerCallback(ConnectTimerCallback), null, 3000, 3000);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnConnectSink(IAsyncResult ar)
|
||||
{
|
||||
if (connectTimer != null) { try { connectTimer.Dispose(); } catch (Exception) { } connectTimer = null; }
|
||||
if (wsclient == null) return;
|
||||
|
||||
// Accept the connection
|
||||
@@ -175,7 +271,14 @@ namespace MeshCentralRouter
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log("Websocket TCP failed to connect: " + ex.ToString());
|
||||
Dispose();
|
||||
if (nativeWebSocketFirst == false)
|
||||
{
|
||||
ConnectTimerCallback(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -251,7 +354,7 @@ namespace MeshCentralRouter
|
||||
else
|
||||
{
|
||||
// Read more proxy data
|
||||
try { wsrawstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnProxyResponseSink), this); } catch (Exception) { Dispose(); }
|
||||
try { wsrawstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnProxyResponseSink), this); } catch (Exception) { Dispose(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -288,13 +391,23 @@ namespace MeshCentralRouter
|
||||
pendingSendBuffer = new MemoryStream();
|
||||
pendingSendCall = false;
|
||||
|
||||
// Build extra headers
|
||||
string extraHeadersStr = "";
|
||||
if (extraHeaders != null)
|
||||
{
|
||||
foreach (string key in extraHeaders.Keys) { extraHeadersStr += key + ": " + extraHeaders[key] + "\r\n"; }
|
||||
}
|
||||
|
||||
// Send the HTTP headers
|
||||
Log("Websocket TLS setup, sending HTTP header...");
|
||||
string header;
|
||||
if (AllowCompression) {
|
||||
header = "GET " + url.PathAndQuery + " HTTP/1.1\r\nHost: " + url.Host + "\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Extensions: permessage-deflate; client_no_context_takeover\r\n" + extraHeaders + "\r\n";
|
||||
} else {
|
||||
header = "GET " + url.PathAndQuery + " HTTP/1.1\r\nHost: " + url.Host + "\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n" + extraHeaders + "\r\n";
|
||||
if (AllowCompression)
|
||||
{
|
||||
header = "GET " + url.PathAndQuery + " HTTP/1.1\r\nHost: " + url.Host + "\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Extensions: permessage-deflate; client_no_context_takeover\r\n" + extraHeadersStr + "\r\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
header = "GET " + url.PathAndQuery + " HTTP/1.1\r\nHost: " + url.Host + "\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n" + extraHeadersStr + "\r\n";
|
||||
}
|
||||
SendData(UTF8Encoding.UTF8.GetBytes(header));
|
||||
|
||||
@@ -387,8 +500,25 @@ namespace MeshCentralRouter
|
||||
|
||||
private void PongTimerCallback(object state) { SendPong(null, 0, 0); }
|
||||
|
||||
private void ConnectTimerCallback(object state) {
|
||||
// Switch from C# sockets to native sockets
|
||||
if ((nativeWebSocketFirst == false) && (this.state == ConnectionStates.Connecting))
|
||||
{
|
||||
Log("Switching to native Websocket");
|
||||
if (pingTimer != null) { try { pingTimer.Dispose(); } catch (Exception) { } pingTimer = null; }
|
||||
if (pongTimer != null) { try { pongTimer.Dispose(); } catch (Exception) { } pongTimer = null; }
|
||||
if (connectTimer != null) { try { connectTimer.Dispose(); } catch (Exception) { } connectTimer = null; }
|
||||
if (wsstream != null) { try { wsstream.Close(); } catch (Exception) { } try { wsstream.Dispose(); } catch (Exception) { } wsstream = null; }
|
||||
if (wsclient != null) { wsclient = null; }
|
||||
if (pendingSendBuffer != null) { pendingSendBuffer.Dispose(); pendingSendBuffer = null; }
|
||||
nativeWebSocketFirst = true;
|
||||
Start(this.url, this.tlsCertFingerprint, this.tlsCertFingerprint2, true);
|
||||
}
|
||||
}
|
||||
|
||||
private int ProcessBuffer(byte[] buffer, int offset, int len)
|
||||
{
|
||||
TlsDump("InRaw", buffer, offset, len);
|
||||
string ss = UTF8Encoding.UTF8.GetString(buffer, offset, len);
|
||||
|
||||
if (state == ConnectionStates.Connecting)
|
||||
@@ -479,15 +609,18 @@ namespace MeshCentralRouter
|
||||
if (((op & 0x40) != 0) && (inflateMemory != null))
|
||||
{
|
||||
// This is a deflate compressed frame
|
||||
inflateMemory.SetLength(0);
|
||||
inflateMemory.Write(data, offset, len);
|
||||
inflateMemory.Write(inflateEnd, 0, 4);
|
||||
inflateMemory.Seek(0, SeekOrigin.Begin);
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
inflate.CopyTo(memoryStream);
|
||||
data = memoryStream.GetBuffer();
|
||||
offset = 0;
|
||||
len = (int)memoryStream.Length;
|
||||
lock (inflateMemory)
|
||||
{
|
||||
inflateMemory.SetLength(0);
|
||||
inflateMemory.Write(data, offset, len);
|
||||
inflateMemory.Write(inflateEnd, 0, 4);
|
||||
inflateMemory.Seek(0, SeekOrigin.Begin);
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
inflate.CopyTo(memoryStream);
|
||||
data = memoryStream.GetBuffer();
|
||||
offset = 0;
|
||||
len = (int)memoryStream.Length;
|
||||
}
|
||||
}
|
||||
|
||||
switch (op & 0x0F)
|
||||
@@ -495,12 +628,14 @@ namespace MeshCentralRouter
|
||||
case 0x01: // This is a text frame
|
||||
{
|
||||
Log("Websocket got string data, len = " + len);
|
||||
TlsDump("InStr", data, offset, len);
|
||||
if (onStringData != null) { onStringData(this, UTF8Encoding.UTF8.GetString(data, offset, len), orglen); }
|
||||
break;
|
||||
}
|
||||
case 0x02: // This is a birnay frame
|
||||
{
|
||||
Log("Websocket got binary data, len = " + len);
|
||||
TlsDump("InBin", data, offset, len);
|
||||
if (onBinaryData != null) { onBinaryData(this, data, offset, len, orglen); }
|
||||
break;
|
||||
}
|
||||
@@ -556,20 +691,42 @@ namespace MeshCentralRouter
|
||||
|
||||
private bool VerifyServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
if (tlsCertFingerprint == null) return true;
|
||||
if ((tlsCertFingerprint.Length == 32) && (certificate.GetCertHashString().Equals(tlsCertFingerprint))) { return true; }
|
||||
if (tlsCertFingerprint.Length == 96)
|
||||
{
|
||||
if (GetMeshCertHash(certificate).Equals(tlsCertFingerprint)) { return true; }
|
||||
if (GetMeshKeyHash(certificate).Equals(tlsCertFingerprint)) { return true; }
|
||||
}
|
||||
|
||||
string hash1 = GetMeshCertHash(certificate);
|
||||
string hash2 = certificate.GetCertHashString();
|
||||
Log("VerifyServerCertificate: tlsCertFingerprint = " + tlsCertFingerprint);
|
||||
Log("VerifyServerCertificate: Hash1 = " + hash1);
|
||||
Log("VerifyServerCertificate: Hash2 = " + hash2);
|
||||
return ((tlsCertFingerprint == GetMeshKeyHash(certificate)) || (tlsCertFingerprint == certificate.GetCertHashString()));
|
||||
//Debug("Verify cert: " + hash1);
|
||||
|
||||
if (TLSCertCheck == TLSCertificateCheck.Ignore)
|
||||
{
|
||||
// Ignore certificate check
|
||||
return true;
|
||||
}
|
||||
else if (TLSCertCheck == TLSCertificateCheck.Fingerprint)
|
||||
{
|
||||
// Fingerprint certificate check
|
||||
if (tlsCertFingerprint == null) return true;
|
||||
if ((tlsCertFingerprint.Length == 32) && (certificate.GetCertHashString().Equals(tlsCertFingerprint))) { return true; }
|
||||
if (tlsCertFingerprint.Length == 96)
|
||||
{
|
||||
if (GetMeshCertHash(certificate).Equals(tlsCertFingerprint)) { return true; }
|
||||
if (GetMeshKeyHash(certificate).Equals(tlsCertFingerprint)) { return true; }
|
||||
}
|
||||
|
||||
Log("VerifyServerCertificate: tlsCertFingerprint = " + tlsCertFingerprint);
|
||||
Log("VerifyServerCertificate: Hash1 = " + hash1);
|
||||
Log("VerifyServerCertificate: Hash2 = " + hash2);
|
||||
return ((tlsCertFingerprint == GetMeshKeyHash(certificate)) || (tlsCertFingerprint == certificate.GetCertHashString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal certificate check
|
||||
if (chain.Build(new X509Certificate2(certificate)) == true) return true;
|
||||
|
||||
// Check that the remote certificate is the expected one
|
||||
if ((tlsCertFingerprint != null) && ((tlsCertFingerprint == certificate.GetCertHashString()) || (tlsCertFingerprint == GetMeshKeyHash(certificate)) || (tlsCertFingerprint == GetMeshCertHash(certificate)))) { return true; }
|
||||
if ((tlsCertFingerprint2 != null) && ((tlsCertFingerprint2 == certificate.GetCertHashString()) || (tlsCertFingerprint2 == GetMeshKeyHash(certificate)) || (tlsCertFingerprint2 == GetMeshCertHash(certificate)))) { return true; }
|
||||
failedTlsCert = new X509Certificate2(certificate);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int SendString(string data)
|
||||
@@ -577,117 +734,192 @@ namespace MeshCentralRouter
|
||||
if (state != ConnectionStates.Connected) return 0;
|
||||
Log("WebSocketClient-SEND-String: " + data);
|
||||
byte[] buf = UTF8Encoding.UTF8.GetBytes(data);
|
||||
return SendFragment(buf, 0, buf.Length, 129);
|
||||
return SendFragment(buf, 0, buf.Length, 129, true);
|
||||
}
|
||||
|
||||
public int SendBinary(byte[] data)
|
||||
{
|
||||
Log("WebSocketClient-SEND-Binary-Len:" + data.Length);
|
||||
return SendFragment(data, 0, data.Length, 130);
|
||||
return SendFragment(data, 0, data.Length, 130, false);
|
||||
}
|
||||
|
||||
public int SendBinary(byte[] data, int offset, int len) {
|
||||
public int SendBinary(byte[] data, int offset, int len)
|
||||
{
|
||||
Log("WebSocketClient-SEND-Binary-Len:" + len);
|
||||
return SendFragment(data, offset, len, 130);
|
||||
return SendFragment(data, offset, len, 130, false);
|
||||
}
|
||||
|
||||
public int SendPing(byte[] data, int offset, int len)
|
||||
{
|
||||
Log("WebSocketClient-SEND-Ping");
|
||||
return SendFragment(null, 0, 0, 137);
|
||||
return SendFragment(null, 0, 0, 137, true);
|
||||
}
|
||||
|
||||
public int SendPong(byte[] data, int offset, int len)
|
||||
{
|
||||
Log("WebSocketClient-SEND-Pong");
|
||||
return SendFragment(null, 0, 0, 138);
|
||||
return SendFragment(null, 0, 0, 138, true);
|
||||
}
|
||||
|
||||
// This controls the flow of fragments being sent, queuing send operations if needed
|
||||
private Task pendingSend = null;
|
||||
private List<pendingSendClass> pendingSends = new List<pendingSendClass>();
|
||||
private class pendingSendClass
|
||||
{
|
||||
public pendingSendClass(byte[] data, int offset, int len, byte op) { this.data = data; this.offset = offset; this.len = len; this.op = op; }
|
||||
public byte[] data;
|
||||
public int offset;
|
||||
public int len;
|
||||
public byte op;
|
||||
}
|
||||
|
||||
// Fragment op code (129 = text, 130 = binary)
|
||||
public int SendFragment(byte[] data, int offset, int len, byte op)
|
||||
// ownershipReleased = True is the memory in data is not owned anymore.
|
||||
private int SendFragment(byte[] data, int offset, int len, byte op, bool ownershipReleased)
|
||||
{
|
||||
lock (mainLock)
|
||||
TlsDump("Out(" + op + ")", data, offset, len);
|
||||
if (ws != null)
|
||||
{
|
||||
if (state != ConnectionStates.Connected) return 0;
|
||||
byte[] buf;
|
||||
if ((data == null) || (len == 0)) return 0;
|
||||
|
||||
// If deflate is active, attempt to compress the data here.
|
||||
if ((deflateMemory != null) && (len > 32) && (AllowCompression))
|
||||
if (ownershipReleased == false)
|
||||
{
|
||||
deflateMemory.SetLength(0);
|
||||
deflateMemory.Write(inflateStart, 0, 14);
|
||||
DeflateStream deflate = new DeflateStream(deflateMemory, CompressionMode.Compress, true);
|
||||
deflate.Write(data, offset, len);
|
||||
deflate.Dispose();
|
||||
deflate = null;
|
||||
if (deflateMemory.Length < len)
|
||||
// Since this is going into a aynsc send or in a queue, copy the outgoing data into a new buffer.
|
||||
byte[] buf = new byte[len];
|
||||
Array.Copy(data, offset, buf, 0, len);
|
||||
data = buf;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
// Using native websocket
|
||||
lock (pendingSends)
|
||||
{
|
||||
if (pendingSend != null)
|
||||
{
|
||||
// Use the compressed data
|
||||
int newlen = (int)deflateMemory.Length;
|
||||
buf = deflateMemory.GetBuffer();
|
||||
len = newlen - 14;
|
||||
op |= 0x40; // Add compression op
|
||||
// A send operating is already being processes, queue this send.
|
||||
pendingSends.Add(new pendingSendClass(data, 0, len, op));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't use the compress data
|
||||
// Convert the string into a buffer with 4 byte of header space.
|
||||
buf = new byte[14 + len];
|
||||
Array.Copy(data, offset, buf, 14, len);
|
||||
// No send operations being performed now, send this fragment now.
|
||||
ArraySegment<byte> arr = new ArraySegment<byte>(data, offset, len);
|
||||
WebSocketMessageType msgType = ((op == 129) ? WebSocketMessageType.Text : WebSocketMessageType.Binary);
|
||||
pendingSend = ws.SendAsync(arr, msgType, true, CTS.Token);
|
||||
pendingSend.ContinueWith(antecedent => SendFragmentDone());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert the string into a buffer with 4 byte of header space.
|
||||
buf = new byte[14 + len];
|
||||
if (len > 0) { Array.Copy(data, offset, buf, 14, len); }
|
||||
}
|
||||
|
||||
// Check that everything is ok
|
||||
if (len < 0) { Dispose(); return 0; }
|
||||
|
||||
// Set the mask to a cryptographic random value and XOR the data
|
||||
byte[] rand = new byte[4];
|
||||
CryptoRandom.GetBytes(rand);
|
||||
Array.Copy(rand, 0, buf, 10, 4);
|
||||
for (int x = 0; x < len; x++) { buf[x + 14] ^= rand[x % 4]; }
|
||||
|
||||
if (len < 126)
|
||||
{
|
||||
// Small fragment
|
||||
buf[8] = op;
|
||||
buf[9] = (byte)((len & 0x7F) + 128); // Add 128 to indicate the mask is present
|
||||
SendData(buf, 8, len + 6);
|
||||
}
|
||||
else if (len < 65535)
|
||||
{
|
||||
// Medium fragment
|
||||
buf[6] = op;
|
||||
buf[7] = 126 + 128; // Add 128 to indicate the mask is present
|
||||
buf[8] = (byte)((len >> 8) & 0xFF);
|
||||
buf[9] = (byte)(len & 0xFF);
|
||||
SendData(buf, 6, len + 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Large fragment
|
||||
buf[0] = op;
|
||||
buf[1] = 127 + 128; // Add 128 to indicate the mask is present
|
||||
buf[6] = (byte)((len >> 24) & 0xFF);
|
||||
buf[7] = (byte)((len >> 16) & 0xFF);
|
||||
buf[8] = (byte)((len >> 8) & 0xFF);
|
||||
buf[9] = (byte)(len & 0xFF);
|
||||
SendData(buf, 0, len + 14);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Using C# websocket
|
||||
lock (mainLock)
|
||||
{
|
||||
if (state != ConnectionStates.Connected) return 0;
|
||||
byte[] buf;
|
||||
|
||||
// If deflate is active, attempt to compress the data here.
|
||||
if ((deflateMemory != null) && (len > 32) && (AllowCompression))
|
||||
{
|
||||
deflateMemory.SetLength(0);
|
||||
DeflateStream deflate = new DeflateStream(deflateMemory, CompressionMode.Compress, true);
|
||||
deflate.Write(data, offset, len);
|
||||
deflate.Dispose();
|
||||
deflate = null;
|
||||
if (deflateMemory.Length < len)
|
||||
{
|
||||
// Copy to a new buffer, this is needed because we do async send operation
|
||||
int newlen = (int)deflateMemory.Length;
|
||||
buf = new byte[14 + newlen];
|
||||
Array.Copy(deflateMemory.GetBuffer(), 0, buf, 14, newlen);
|
||||
len = newlen;
|
||||
op |= 0x40; // Add compression op
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't use the compress data
|
||||
// Convert the string into a buffer with 4 byte of header space.
|
||||
buf = new byte[14 + len];
|
||||
Array.Copy(data, offset, buf, 14, len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert the string into a buffer with 14 bytea of header space.
|
||||
buf = new byte[14 + len];
|
||||
if (len > 0) { Array.Copy(data, offset, buf, 14, len); }
|
||||
}
|
||||
|
||||
// Check that everything is ok
|
||||
if (len < 0) { Dispose(); return 0; }
|
||||
|
||||
// Set the mask to a cryptographic random value and XOR the data
|
||||
byte[] rand = new byte[4];
|
||||
CryptoRandom.GetBytes(rand);
|
||||
Array.Copy(rand, 0, buf, 10, 4);
|
||||
for (int x = 0; x < len; x++) { buf[x + 14] ^= rand[x % 4]; }
|
||||
|
||||
if (len < 126)
|
||||
{
|
||||
// Small fragment
|
||||
buf[8] = op;
|
||||
buf[9] = (byte)((len & 0x7F) + 128); // Add 128 to indicate the mask is present
|
||||
SendData(buf, 8, len + 6);
|
||||
}
|
||||
else if (len < 65535)
|
||||
{
|
||||
// Medium fragment
|
||||
buf[6] = op;
|
||||
buf[7] = 126 + 128; // Add 128 to indicate the mask is present
|
||||
buf[8] = (byte)((len >> 8) & 0xFF);
|
||||
buf[9] = (byte)(len & 0xFF);
|
||||
SendData(buf, 6, len + 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Large fragment
|
||||
buf[0] = op;
|
||||
buf[1] = 127 + 128; // Add 128 to indicate the mask is present
|
||||
buf[6] = (byte)((len >> 24) & 0xFF);
|
||||
buf[7] = (byte)((len >> 16) & 0xFF);
|
||||
buf[8] = (byte)((len >> 8) & 0xFF);
|
||||
buf[9] = (byte)(len & 0xFF);
|
||||
SendData(buf, 0, len + 14);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Called when a fragment is done sending. We look to send the next one or signal that we can accept more data
|
||||
private void SendFragmentDone()
|
||||
{
|
||||
bool q = false;
|
||||
lock (pendingSends)
|
||||
{
|
||||
pendingSend = null;
|
||||
if (pendingSends.Count > 0)
|
||||
{
|
||||
// There is more send operation pending, send the next one now.
|
||||
pendingSendClass p = pendingSends[0];
|
||||
pendingSends.RemoveAt(0);
|
||||
ArraySegment<byte> arr = new ArraySegment<byte>(p.data, p.offset, p.len);
|
||||
WebSocketMessageType msgType = ((p.op == 129) ? WebSocketMessageType.Text : WebSocketMessageType.Binary);
|
||||
pendingSend = ws.SendAsync(arr, msgType, true, CTS.Token);
|
||||
pendingSend.ContinueWith(antecedent => SendFragmentDone());
|
||||
}
|
||||
else { q = true; } // No pending send operations, signal ok to send more.
|
||||
}
|
||||
if ((q == true) && (onSendOk != null)) { onSendOk(this); }
|
||||
}
|
||||
|
||||
private void SendData(byte[] buf) { SendData(buf, 0, buf.Length); }
|
||||
|
||||
private void SendData(byte[] buf, int off, int len)
|
||||
{
|
||||
TlsDump("OutRaw", buf, off, len);
|
||||
if (pendingSendCall)
|
||||
{
|
||||
lock (pendingSendBuffer) { pendingSendBuffer.Write(buf, off, len); }
|
||||
@@ -714,9 +946,12 @@ namespace MeshCentralRouter
|
||||
bool IsSuccess = Win32Api.WinHttpGetProxyForUrl(WinHttpSession, DestinationUrl, ref ProxyOptions, ref ProxyInfo);
|
||||
Win32Api.WinHttpCloseHandle(WinHttpSession);
|
||||
|
||||
if (IsSuccess) {
|
||||
if (IsSuccess)
|
||||
{
|
||||
return ProxyInfo.lpszProxy;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Error: {0}", Win32Api.GetLastError());
|
||||
return null;
|
||||
}
|
||||
@@ -726,7 +961,9 @@ namespace MeshCentralRouter
|
||||
{
|
||||
lock (mainLock)
|
||||
{
|
||||
if (readPaused == true) return;
|
||||
readPaused = true;
|
||||
if (ws != null) { receiveLock.Wait(); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -736,11 +973,76 @@ namespace MeshCentralRouter
|
||||
{
|
||||
if (readPaused == false) return;
|
||||
readPaused = false;
|
||||
if (shouldRead == true)
|
||||
if (ws != null)
|
||||
{
|
||||
shouldRead = false;
|
||||
try { wsstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnTlsDataSink), this); } catch (Exception) { }
|
||||
receiveLock.Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shouldRead == true)
|
||||
{
|
||||
shouldRead = false;
|
||||
try { wsstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnTlsDataSink), this); } catch (Exception) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ReceiveLoop()
|
||||
{
|
||||
SetState(ConnectionStates.Connected);
|
||||
var loopToken = CTS.Token;
|
||||
MemoryStream outputStream = null;
|
||||
WebSocketReceiveResult receiveResult = null;
|
||||
var buffer = new byte[8192];
|
||||
ArraySegment<byte> bufferEx = new ArraySegment<byte>(buffer);
|
||||
try
|
||||
{
|
||||
while (!loopToken.IsCancellationRequested)
|
||||
{
|
||||
outputStream = new MemoryStream(8192);
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
Task<WebSocketReceiveResult> t = ws.ReceiveAsync(bufferEx, CTS.Token);
|
||||
t.Wait();
|
||||
receiveResult = t.Result;
|
||||
if (receiveResult.MessageType != WebSocketMessageType.Close) { outputStream.Write(buffer, 0, receiveResult.Count); }
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
outputStream?.Dispose();
|
||||
SetState(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
while (!receiveResult.EndOfMessage);
|
||||
if (receiveResult.MessageType == WebSocketMessageType.Close) break;
|
||||
outputStream.Position = 0;
|
||||
|
||||
receiveLock.Wait(); // Pause reading if needed
|
||||
receiveLock.Release();
|
||||
|
||||
if (receiveResult.MessageType == WebSocketMessageType.Text)
|
||||
{
|
||||
Log("Websocket got string data, len = " + (int)outputStream.Length);
|
||||
TlsDump("InStr", outputStream.GetBuffer(), 0, (int)outputStream.Length);
|
||||
if (onStringData != null) { onStringData(this, UTF8Encoding.UTF8.GetString(outputStream.GetBuffer(), 0, (int)outputStream.Length), (int)outputStream.Length); }
|
||||
}
|
||||
else if (receiveResult.MessageType == WebSocketMessageType.Binary)
|
||||
{
|
||||
Log("Websocket got binary data, len = " + (int)outputStream.Length);
|
||||
TlsDump("InBin", outputStream.GetBuffer(), 0, (int)outputStream.Length);
|
||||
if (onBinaryData != null) { onBinaryData(this, outputStream.GetBuffer(), 0, (int)outputStream.Length, (int)outputStream.Length); }
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (TaskCanceledException) { }
|
||||
finally
|
||||
{
|
||||
outputStream?.Dispose();
|
||||
SetState(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -39,4 +39,4 @@
|
||||
</setting>
|
||||
</MeshStateMonitor.Properties.Settings>
|
||||
</userSettings>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2009-2021 Intel Corporation
|
||||
Copyright 2009-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
Reference in New Issue
Block a user