diff --git a/Configuration/GlobalAssemblyInfo.cs b/Configuration/GlobalAssemblyInfo.cs index 64f88b553..06a5a1d5b 100644 --- a/Configuration/GlobalAssemblyInfo.cs +++ b/Configuration/GlobalAssemblyInfo.cs @@ -15,7 +15,7 @@ internal static class RevisionClass public const string Major = "3"; public const string Minor = "8"; public const string Build = "3"; - public const string Revision = "3152"; + public const string Revision = "3154"; public const string MainVersion = Major + "." + Minor; public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision; diff --git a/Configuration/Version.defs b/Configuration/Version.defs index 57938be3a..d0b88e0b7 100644 --- a/Configuration/Version.defs +++ b/Configuration/Version.defs @@ -1,4 +1,4 @@ %COREVERSION%=3 -%REVISION%=3152 +%REVISION%=3154 %MINOR%=8 %MAJOR%=3 diff --git a/PluginsSupport/Interfaces.cs b/PluginsSupport/Interfaces.cs index 3f78832ad..ce0d8e533 100644 --- a/PluginsSupport/Interfaces.cs +++ b/PluginsSupport/Interfaces.cs @@ -59,6 +59,11 @@ namespace VisualPascalABCPlugins void GetGUI(List MenuItems, List ToolBarItems); } + public interface IExtendedVisualPascalABCPlugin: IVisualPascalABCPlugin + { + void AfterAddInGUI(); + } + public enum VisualEnvironmentState { diff --git a/Release/pabcversion.txt b/Release/pabcversion.txt index 9643a6e59..3c25999b7 100644 --- a/Release/pabcversion.txt +++ b/Release/pabcversion.txt @@ -1 +1 @@ -3.8.3.3152 +3.8.3.3154 diff --git a/ReleaseGenerators/PascalABCNET_version.nsh b/ReleaseGenerators/PascalABCNET_version.nsh index 552d23456..995b2694d 100644 --- a/ReleaseGenerators/PascalABCNET_version.nsh +++ b/ReleaseGenerators/PascalABCNET_version.nsh @@ -1 +1 @@ -!define VERSION '3.8.3.3152' +!define VERSION '3.8.3.3154' diff --git a/VisualPascalABCNET/DS/PluginsController/PluginsController.cs b/VisualPascalABCNET/DS/PluginsController/PluginsController.cs index ba73ea08c..8e03deaee 100644 --- a/VisualPascalABCNET/DS/PluginsController/PluginsController.cs +++ b/VisualPascalABCNET/DS/PluginsController/PluginsController.cs @@ -121,6 +121,8 @@ namespace VisualPascalABCPlugins //ToolStrip.Refresh(); if (ToolStripMenuItem.Visible == false) ToolStripMenuItem.Visible = true; + if (Plugin is IExtendedVisualPascalABCPlugin iex) + iex.AfterAddInGUI(); } void button_Click(object sender, EventArgs e) { diff --git a/VisualPlugins/TraningControlPlugin/LoginForm.Designer.cs b/VisualPlugins/TraningControlPlugin/LoginForm.Designer.cs index 43413f764..8a7f532f0 100644 --- a/VisualPlugins/TraningControlPlugin/LoginForm.Designer.cs +++ b/VisualPlugins/TraningControlPlugin/LoginForm.Designer.cs @@ -41,17 +41,22 @@ this.groupImage = new System.Windows.Forms.PictureBox(); this.PluginImage = new System.Windows.Forms.PictureBox(); this.PluginImageAuthorized = new System.Windows.Forms.PictureBox(); + this.panelUnAuthorized = new System.Windows.Forms.Panel(); + this.panelAuthorized = new System.Windows.Forms.Panel(); + this.labelUserName = new System.Windows.Forms.Label(); ((System.ComponentModel.ISupportInitialize)(this.userImage)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.groupImage)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.PluginImage)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.PluginImageAuthorized)).BeginInit(); + this.panelUnAuthorized.SuspendLayout(); + this.panelAuthorized.SuspendLayout(); this.SuspendLayout(); // // groupNamesBox // this.groupNamesBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.groupNamesBox.FormattingEnabled = true; - this.groupNamesBox.Location = new System.Drawing.Point(114, 12); + this.groupNamesBox.Location = new System.Drawing.Point(114, 19); this.groupNamesBox.Name = "groupNamesBox"; this.groupNamesBox.Size = new System.Drawing.Size(258, 21); this.groupNamesBox.TabIndex = 1; @@ -61,7 +66,7 @@ // this.usersNamesBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.usersNamesBox.FormattingEnabled = true; - this.usersNamesBox.Location = new System.Drawing.Point(114, 50); + this.usersNamesBox.Location = new System.Drawing.Point(114, 59); this.usersNamesBox.Name = "usersNamesBox"; this.usersNamesBox.Size = new System.Drawing.Size(258, 21); this.usersNamesBox.TabIndex = 2; @@ -69,7 +74,7 @@ // labelGroup // this.labelGroup.AutoSize = true; - this.labelGroup.Location = new System.Drawing.Point(63, 15); + this.labelGroup.Location = new System.Drawing.Point(63, 22); this.labelGroup.Name = "labelGroup"; this.labelGroup.Size = new System.Drawing.Size(45, 13); this.labelGroup.TabIndex = 3; @@ -78,7 +83,7 @@ // labelUser // this.labelUser.AutoSize = true; - this.labelUser.Location = new System.Drawing.Point(25, 53); + this.labelUser.Location = new System.Drawing.Point(25, 62); this.labelUser.Name = "labelUser"; this.labelUser.Size = new System.Drawing.Size(83, 13); this.labelUser.TabIndex = 4; @@ -86,7 +91,7 @@ // // passwordBox // - this.passwordBox.Location = new System.Drawing.Point(114, 92); + this.passwordBox.Location = new System.Drawing.Point(114, 99); this.passwordBox.Name = "passwordBox"; this.passwordBox.Size = new System.Drawing.Size(258, 20); this.passwordBox.TabIndex = 5; @@ -94,7 +99,7 @@ // labelPassword // this.labelPassword.AutoSize = true; - this.labelPassword.Location = new System.Drawing.Point(60, 95); + this.labelPassword.Location = new System.Drawing.Point(60, 102); this.labelPassword.Name = "labelPassword"; this.labelPassword.Size = new System.Drawing.Size(48, 13); this.labelPassword.TabIndex = 6; @@ -102,7 +107,7 @@ // // enterButton // - this.enterButton.Location = new System.Drawing.Point(87, 131); + this.enterButton.Location = new System.Drawing.Point(87, 138); this.enterButton.Name = "enterButton"; this.enterButton.Size = new System.Drawing.Size(118, 34); this.enterButton.TabIndex = 8; @@ -113,7 +118,7 @@ // closeButton // this.closeButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.closeButton.Location = new System.Drawing.Point(225, 131); + this.closeButton.Location = new System.Drawing.Point(225, 138); this.closeButton.Name = "closeButton"; this.closeButton.Size = new System.Drawing.Size(118, 34); this.closeButton.TabIndex = 7; @@ -124,7 +129,7 @@ // userImage // this.userImage.InitialImage = null; - this.userImage.Location = new System.Drawing.Point(378, 45); + this.userImage.Location = new System.Drawing.Point(378, 54); this.userImage.Name = "userImage"; this.userImage.Size = new System.Drawing.Size(32, 32); this.userImage.TabIndex = 10; @@ -133,7 +138,7 @@ // groupImage // this.groupImage.InitialImage = null; - this.groupImage.Location = new System.Drawing.Point(378, 7); + this.groupImage.Location = new System.Drawing.Point(378, 14); this.groupImage.Name = "groupImage"; this.groupImage.Size = new System.Drawing.Size(32, 32); this.groupImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; @@ -144,7 +149,7 @@ // this.PluginImage.BackColor = System.Drawing.Color.Magenta; this.PluginImage.Image = ((System.Drawing.Image)(resources.GetObject("PluginImage.Image"))); - this.PluginImage.Location = new System.Drawing.Point(379, 95); + this.PluginImage.Location = new System.Drawing.Point(385, 146); this.PluginImage.Margin = new System.Windows.Forms.Padding(6); this.PluginImage.Name = "PluginImage"; this.PluginImage.Size = new System.Drawing.Size(25, 26); @@ -157,31 +162,58 @@ this.PluginImageAuthorized.BackColor = System.Drawing.Color.Magenta; this.PluginImageAuthorized.Image = ((System.Drawing.Image)(resources.GetObject("PluginImageAuthorized.Image"))); this.PluginImageAuthorized.InitialImage = null; - this.PluginImageAuthorized.Location = new System.Drawing.Point(379, 131); + this.PluginImageAuthorized.Location = new System.Drawing.Point(351, 146); this.PluginImageAuthorized.Name = "PluginImageAuthorized"; this.PluginImageAuthorized.Size = new System.Drawing.Size(25, 26); this.PluginImageAuthorized.TabIndex = 12; this.PluginImageAuthorized.TabStop = false; this.PluginImageAuthorized.Visible = false; // + // panelUnAuthorized + // + this.panelUnAuthorized.Controls.Add(this.groupNamesBox); + this.panelUnAuthorized.Controls.Add(this.passwordBox); + this.panelUnAuthorized.Controls.Add(this.usersNamesBox); + this.panelUnAuthorized.Controls.Add(this.labelUser); + this.panelUnAuthorized.Controls.Add(this.labelGroup); + this.panelUnAuthorized.Controls.Add(this.labelPassword); + this.panelUnAuthorized.Controls.Add(this.groupImage); + this.panelUnAuthorized.Controls.Add(this.userImage); + this.panelUnAuthorized.Location = new System.Drawing.Point(0, 0); + this.panelUnAuthorized.Name = "panelUnAuthorized"; + this.panelUnAuthorized.Size = new System.Drawing.Size(422, 132); + this.panelUnAuthorized.TabIndex = 13; + // + // panelAuthorized + // + this.panelAuthorized.Controls.Add(this.labelUserName); + this.panelAuthorized.Location = new System.Drawing.Point(0, 0); + this.panelAuthorized.Name = "panelAuthorized"; + this.panelAuthorized.Size = new System.Drawing.Size(422, 132); + this.panelAuthorized.TabIndex = 14; + // + // labelUserName + // + this.labelUserName.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204))); + this.labelUserName.Location = new System.Drawing.Point(25, 14); + this.labelUserName.Name = "labelUserName"; + this.labelUserName.Size = new System.Drawing.Size(372, 26); + this.labelUserName.TabIndex = 11; + this.labelUserName.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // // LoginForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.CancelButton = this.closeButton; - this.ClientSize = new System.Drawing.Size(422, 175); + this.ClientSize = new System.Drawing.Size(422, 191); + this.Controls.Add(this.panelUnAuthorized); + this.Controls.Add(this.panelAuthorized); this.Controls.Add(this.PluginImageAuthorized); this.Controls.Add(this.PluginImage); - this.Controls.Add(this.userImage); - this.Controls.Add(this.groupImage); this.Controls.Add(this.closeButton); this.Controls.Add(this.enterButton); - this.Controls.Add(this.labelPassword); - this.Controls.Add(this.passwordBox); - this.Controls.Add(this.labelUser); - this.Controls.Add(this.labelGroup); - this.Controls.Add(this.usersNamesBox); - this.Controls.Add(this.groupNamesBox); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "LoginForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; @@ -191,8 +223,10 @@ ((System.ComponentModel.ISupportInitialize)(this.groupImage)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.PluginImage)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.PluginImageAuthorized)).EndInit(); + this.panelUnAuthorized.ResumeLayout(false); + this.panelUnAuthorized.PerformLayout(); + this.panelAuthorized.ResumeLayout(false); this.ResumeLayout(false); - this.PerformLayout(); } @@ -210,5 +244,8 @@ private System.Windows.Forms.PictureBox userImage; public System.Windows.Forms.PictureBox PluginImage; public System.Windows.Forms.PictureBox PluginImageAuthorized; + private System.Windows.Forms.Panel panelUnAuthorized; + private System.Windows.Forms.Label labelUserName; + private System.Windows.Forms.Panel panelAuthorized; } } \ No newline at end of file diff --git a/VisualPlugins/TraningControlPlugin/LoginForm.cs b/VisualPlugins/TraningControlPlugin/LoginForm.cs index d8aa0b066..4a3c23736 100644 --- a/VisualPlugins/TraningControlPlugin/LoginForm.cs +++ b/VisualPlugins/TraningControlPlugin/LoginForm.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Data; +using System.IO; using System.Drawing; using System.Linq; using System.Text; @@ -15,6 +16,7 @@ namespace DBAccessPluginNamespace { public SiteAccessProvider SiteProvider = null; public VisualPascalABCPlugin_TeacherControlPlugin Plugin = null; + public bool Authorized = false; public LoginForm(VisualPascalABCPlugin_TeacherControlPlugin Plugin) { @@ -22,7 +24,205 @@ namespace DBAccessPluginNamespace InitializeComponent(); } - public bool Authorized = false; + public bool TryCreateAuthFile(string filename, string login, string pass) + { + var res = true; + try + { + using (var sw = new System.IO.StreamWriter(filename)) + { + sw.WriteLine(login); + sw.WriteLine(pass); + } + } + catch (Exception) + { + res = false; + } + return res; + } + + public bool IsRootDirectory(string path) + { + var isroot = false; + try + { + var full = Path.GetFullPath(path); + var root = Path.GetPathRoot(full); + if (full == root) + isroot = true; + } + catch { } + return isroot; + } + + public bool CalcParentDirectory(string path, out string parent) + { + parent = ""; + if (IsRootDirectory(path)) + return false; + var hasparent = false; + try + { + var full = Path.GetFullPath(path); + parent = Directory.GetParent(full).FullName; + hasparent = true; + } + catch { } + return hasparent; + } + + public void WriteLoginPassToAuthDat(string login, string pass) + { + // SSM 04.08.22 Сохранить в auth.dat логин и пароль + // Плохо вот что. Мы можем зайти из папки, в которой есть lightpt.dat, а потом перейти в папку, где его нет + // Мы также можем скопировать lightpt.dat в корень + + // SSM 04.08.22 Поэтому надо проверить, что в текущей папке находится lightpt.dat и эта папка не корневая. В принципе, просто в корне этого диска можно + // После этого перейти в корень диска и там создать этот файл + + // SSM 11.08.22 При ручной авторизации - сохранение + // Мехмат: auth сохраняется в корень сетевого диска + // Дома: auth сохраняется в папке на уровень выше текущей. Если это невозможно, то в текущей папке. + // Если это диск C, то тоже не сохранять и тогда сохранять в текущей + + // дома сохранять авторизацию на уровень выше текущего если это не корень. Если корень, то в текущий + // на мехмате сохранять авторизацию в корень сетевого диска если он не защищен от записи + // вопрос: если на мехмате текущий каталог - PABCWork.NET, то надо ли сохранять авторизацию? + // это происходит тогда когда школьник смонтировал сетевой диск, но зашел в Паскаль по кнопке Пуск или с рабочего стола + // можно попробовать поискать сетевой диск + + var AuthFileFullName = ""; + if (Plugin.IsMechmath()) + { + // Найти корень сетевого диска + // Если сетевой - текущий, то в него (это как правило) + var workDir = Plugin.WorkingDirectory(); + var root = Path.GetPathRoot(workDir); + System.IO.DriveInfo di = new System.IO.DriveInfo(root); + bool b = false; + if (di.DriveType == System.IO.DriveType.Network) + { + var auth = System.IO.Path.Combine(root, "auth.dat"); + b = TryCreateAuthFile(auth, login, pass); + } + + // Если нет, то попытаться найти первый сетевой, где в корне уже есть auth.dat + if (!b) // Если не удалось записать + { + string authName = ""; + foreach (var drive in System.IO.DriveInfo.GetDrives()) + { + if (drive.DriveType != System.IO.DriveType.Network) + continue; + // Проверять, что диск сетевой!!! Для несетевых - нет! + var auth = System.IO.Path.Combine(drive.Name, "auth.dat"); + if (System.IO.File.Exists(auth)) + authName = auth; + } + b = TryCreateAuthFile(authName, login, pass); + } + // Если нет, то попытаться найти первый сетевой (это первый раз когда нет auth + if (!b) // Если не удалось записать + { + string authName = ""; + foreach (var drive in System.IO.DriveInfo.GetDrives()) + { + if (drive.DriveType != System.IO.DriveType.Network) + continue; + // Найти первый сетевой куда можно записать + b = TryCreateAuthFile(authName, login, pass); + if (b) + break; + } + } + // Та редкая ситуация когда школьник заходит первый раз на первом занятии, не подключает диск и залогинивается в PABC + } + else // это домашний компьютер + { + //System.IO.Directory.GetParent + + var workDir = Plugin.WorkingDirectory(); + //Path.GetFullPath + + /// + // сохранить пароль в каталоге на уровень выше WorkingDir. Если это корни дисков или уровнем выше нельзя, то в текущем + // + //var auth = System.IO.Path.Combine(workDir, "auth.dat"); + var b1 = CalcParentDirectory(workDir, out string parent); + bool b = false; + if (b1 && !IsRootDirectory(parent)) + { + // пытаемся в родительском + var auth = System.IO.Path.Combine(parent, "auth.dat"); + b = TryCreateAuthFile(auth, login, pass); + if (b) + AuthFileFullName = auth; // Эта информация нигде не используется - только для тестирования + } + if (!b) + { + // пытаемся в текущем. Если он корень - ну, человек так хотел + var auth = System.IO.Path.Combine(workDir, "auth.dat"); + b = TryCreateAuthFile(auth, login, pass); + if (b) + AuthFileFullName = auth; // Эта информация нигде не используется - только для тестирования + } + } + } + + public void ChangeControlsAfterLogin(string login) + { + try + { + Text = "Авторизация: вход выполнен"; + usersNamesBox.Text = login; + //var login = usersNamesBox.Text; + //var pass = passwordBox.Text; + passwordBox.Text = ""; + enterButton.Text = "Выход"; + passwordBox.Visible = false; + labelPassword.Visible = false; + groupNamesBox.Enabled = false; + usersNamesBox.Enabled = false; + Authorized = true; + Plugin.toolStripButton.ToolTipText = "Авторизация выполнена: " + login; + Plugin.toolStripButton.Image = PluginImageAuthorized.Image; + Plugin.menuItem.Image = PluginImageAuthorized.Image; + this.Icon = VisualPascalABCPlugins.Properties.Resources.IconAuthorized; + closeButton.Focus(); + panelUnAuthorized.SendToBack(); + labelUserName.Text = login; + } + catch (Exception e) + { + MessageBox.Show(e.ToString()); + e = e; + } + } + + public void ChangeControlsAfterLogout() + { + Text = "Авторизация"; + passwordBox.Text = ""; + enterButton.Text = "Вход"; + groupNamesBox.SelectedIndex = -1; + usersNamesBox.Items.Clear(); + usersNamesBox.SelectedIndex = -1; + groupNamesBox.Enabled = true; + usersNamesBox.Enabled = true; + passwordBox.Visible = true; + labelPassword.Visible = true; + Authorized = false; + Plugin.toolStripButton.ToolTipText = "Авторизация: вход не выполнен"; + Plugin.toolStripButton.Image = PluginImage.Image; + Plugin.menuItem.Image = PluginImage.Image; + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LoginForm)); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + panelUnAuthorized.BringToFront(); + labelUserName.Text = ""; + + } + private async void enterButton_Click(object sender, EventArgs e) { if (SiteProvider == null) @@ -30,46 +230,33 @@ namespace DBAccessPluginNamespace if (!Authorized) { - var answer = await SiteProvider.Login("", usersNamesBox.Text, passwordBox.Text); - if(answer == "Success") + try { - //DialogResult = DialogResult.OK; - //Close(); - Text = "Авторизация: вход выполнен"; - passwordBox.Text = ""; - enterButton.Text = "Выход"; - passwordBox.Visible = false; - labelPassword.Visible = false; - groupNamesBox.Enabled = false; - usersNamesBox.Enabled = false; - Authorized = true; - Plugin.toolStripButton.ToolTipText = "Авторизация выполнена: " + SiteProvider.FullFIO; - Plugin.toolStripButton.Image = PluginImageAuthorized.Image; - Plugin.menuItem.Image = PluginImageAuthorized.Image; - this.Icon = VisualPascalABCPlugins.Properties.Resources.IconAuthorized; + if (Text.StartsWith("Авторизация: нет связи с сервером")) + Text = "Авторизация"; + + var answer = await SiteProvider.Login("", usersNamesBox.Text, passwordBox.Text); + if (answer == "Success") + { + WriteLoginPassToAuthDat(usersNamesBox.Text, passwordBox.Text); + ChangeControlsAfterLogin(usersNamesBox.Text); + } + else MessageBox.Show(answer, "Ошибка"); + } + catch (System.Net.Http.HttpRequestException ex) + { + Text = "Авторизация: нет связи с сервером"; closeButton.Focus(); } - else MessageBox.Show(answer,"Ошибка"); + catch (Exception ex) + { + MessageBox.Show(ex.ToString()); + } } else { SiteProvider.Logout(); - Text = "Авторизация"; - passwordBox.Text = ""; - enterButton.Text = "Вход"; - groupNamesBox.SelectedIndex = -1; - usersNamesBox.Items.Clear(); - usersNamesBox.SelectedIndex = -1; - groupNamesBox.Enabled = true; - usersNamesBox.Enabled = true; - passwordBox.Visible = true; - labelPassword.Visible = true; - Authorized = false; - Plugin.toolStripButton.ToolTipText = "Авторизация: вход не выполнен"; - Plugin.toolStripButton.Image = PluginImage.Image; - Plugin.menuItem.Image = PluginImage.Image; - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LoginForm)); - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + ChangeControlsAfterLogout(); } } @@ -81,11 +268,25 @@ namespace DBAccessPluginNamespace throw new Exception("Error in Login form! Site credentials cannot be empty!"); if (groupNamesBox.Items.Count > 0) // Группы уже загружены return; - //groupImage.Image = Properties.Resources.LoadingImg; - var groups = await SiteProvider.GetGroupsNames(); - groupNamesBox.Items.Clear(); - groupNamesBox.Items.AddRange(groups.Split(';').Where(Item => Item != "").ToArray()); - //groupImage.Image = null; + try + { + if (Text.StartsWith("Авторизация: нет связи с сервером")) + Text = "Авторизация"; + //groupImage.Image = Properties.Resources.LoadingImg; + groupNamesBox.Items.Clear(); + var groups = await SiteProvider.GetGroupsNames(); + groupNamesBox.Items.AddRange(groups.Split(';').Where(Item => Item != "").ToArray()); + //groupImage.Image = null; + } + catch (System.Net.Http.HttpRequestException ex) + { + Text = "Авторизация: нет связи с сервером"; + closeButton.Focus(); + } + catch (Exception ex) + { + MessageBox.Show(ex.ToString()); + } } private async void GroupNamesBox_SelectedIndexChanged(object sender, EventArgs e) @@ -95,11 +296,27 @@ namespace DBAccessPluginNamespace if (SiteProvider == null) throw new Exception("Error in Login form! Site credentials cannot be empty!"); - //userImage.Image = Properties.Resources.LoadingImg; - var users = await SiteProvider.GetUsersNames(groupNamesBox.Text); - usersNamesBox.Items.Clear(); - usersNamesBox.Items.AddRange(users.Split(';').Where(Item => Item != "").ToArray()); - //userImage.Image = null; + try + { + if (Text.StartsWith("Авторизация: нет связи с сервером")) + Text = "Авторизация"; + //var t = Text; + //userImage.Image = Properties.Resources.LoadingImg; + usersNamesBox.Items.Clear(); + var users = await SiteProvider.GetUsersNames(groupNamesBox.Text); + usersNamesBox.Items.AddRange(users.Split(';').Where(Item => Item != "").ToArray()); + //userImage.Image = null; + //Text = t; + } + catch (System.Net.Http.HttpRequestException ex) + { + Text = "Авторизация: нет связи с сервером"; + closeButton.Focus(); + } + catch (Exception ex) + { + MessageBox.Show(ex.ToString()); + } } private void cancelButton_Click(object sender, EventArgs e) diff --git a/VisualPlugins/TraningControlPlugin/SiteAccessInfo.cs b/VisualPlugins/TraningControlPlugin/SiteAccessInfo.cs index 91960d69a..047ada4c9 100644 --- a/VisualPlugins/TraningControlPlugin/SiteAccessInfo.cs +++ b/VisualPlugins/TraningControlPlugin/SiteAccessInfo.cs @@ -44,6 +44,7 @@ namespace DBAccessPluginNamespace // Если клиент ещё не создан был, пересоздаём if (client == null) client = new HttpClient(); + client.Timeout = TimeSpan.FromSeconds(10); // Словарик для параметров запроса var values = new Dictionary { @@ -79,6 +80,7 @@ namespace DBAccessPluginNamespace { // Если клиент ещё не создан был, пересоздаём if (client == null) client = new HttpClient(); + client.Timeout = TimeSpan.FromSeconds(10); // Тут не столь важно что отправлять, можно и пустой список параметров var values = new Dictionary { @@ -102,6 +104,7 @@ namespace DBAccessPluginNamespace // Если клиент ещё не создан был, пересоздаём if (client == null) client = new HttpClient(); + client.Timeout = TimeSpan.FromSeconds(10); var values = new Dictionary(); var content = new FormUrlEncodedContent(values); var response = await client.PostAsync(ServAddr + "/groupslist.php", content); @@ -120,6 +123,7 @@ namespace DBAccessPluginNamespace if (ServAddr == "") return "Error"; // Если клиент ещё не создан был, пересоздаём if (client == null) client = new HttpClient(); + client.Timeout = TimeSpan.FromSeconds(10); Group = GroupName; var values = new Dictionary { @@ -145,6 +149,7 @@ namespace DBAccessPluginNamespace FullFIO = fullFIO; Password = password; if (client == null) client = new HttpClient(); + client.Timeout = TimeSpan.FromSeconds(10); // Словарик для параметров запроса var values = new Dictionary diff --git a/VisualPlugins/TraningControlPlugin/TeacherControlPlugin.cs b/VisualPlugins/TraningControlPlugin/TeacherControlPlugin.cs index 6508cf2ed..8351072f7 100644 --- a/VisualPlugins/TraningControlPlugin/TeacherControlPlugin.cs +++ b/VisualPlugins/TraningControlPlugin/TeacherControlPlugin.cs @@ -10,7 +10,7 @@ using DBAccessPluginNamespace; namespace VisualPascalABCPlugins { //имя класса *_VisualPascalABCPlugin - public class VisualPascalABCPlugin_TeacherControlPlugin : IVisualPascalABCPlugin + public class VisualPascalABCPlugin_TeacherControlPlugin : IExtendedVisualPascalABCPlugin { private const string LabelEntered = "Авторизация: "; private const string LabelNotEntered = "Авторизация: вход не выполнен"; @@ -33,12 +33,14 @@ namespace VisualPascalABCPlugins public LoginForm loginForm; - bool firstTime = true; public ToolStripMenuItem menuItem = null; public ToolStripButton toolStripButton = null; + public string AuthFileFullName = ""; + public VisualPascalABCPlugin_TeacherControlPlugin(IWorkbench Workbench) { + User.ServAddr = "https://air.mmcs.sfedu.ru/pascalabc"; loginForm = new LoginForm(this); this.Workbench = Workbench; VisualEnvironmentCompiler = Workbench.VisualEnvironmentCompiler; @@ -51,14 +53,6 @@ namespace VisualPascalABCPlugins } public void Execute() { - if (firstTime) - { - firstTime = false; - menuItem = (ToolStripMenuItem)Item.menuItem; - toolStripButton = (ToolStripButton)Item.toolStripButton; - } - - User.ServAddr = "https://air.mmcs.sfedu.ru/pascalabc"; loginForm.SiteProvider = User; loginForm.ShowDialog(); // OK никогда не будет @@ -74,38 +68,149 @@ namespace VisualPascalABCPlugins }*/ } - public void GetGUI(List MenuItems, List ToolBarItems) + public string FullAuthNameFromNETDisk() { - Item = new PluginGUIItem(StringsPrefix + "NAME", StringsPrefix + "DESCRIPTION", loginForm.PluginImage.Image, loginForm.PluginImage.BackColor, Execute); - MenuItems.Add(Item); - ToolBarItems.Add(Item); + string authName = ""; + try + { + foreach (var drive in System.IO.DriveInfo.GetDrives()) + { + if (drive.DriveType != System.IO.DriveType.Network) + continue; + // Проверять, что диск сетевой!!! Для несетевых - нет! + var auth = System.IO.Path.Combine(drive.Name, "auth.dat"); + if (System.IO.File.Exists(auth)) + authName = auth; + } + } + catch (Exception) + { + } + return authName; } - /*private void BeforeCompileHandler(string filename) // filename - pas-файл + public string WorkingDirectory() { - // Проверяем присутствие файла lightpt.dat - var fi = new System.IO.FileInfo(filename); - var SourceFileDirectory = fi.DirectoryName; + var FileName = Workbench.ServiceContainer.DocumentService.CurrentCodeFileDocument.FileName; + return System.IO.Path.GetDirectoryName(FileName); + } - var FullLightPTName = System.IO.Path.Combine(SourceFileDirectory, "lightpt.dat"); + public string FullLightPTName() + { + var WorkingDir = WorkingDirectory(); + var lightptname = System.IO.Path.Combine(WorkingDir, "lightpt.dat"); + if (System.IO.File.Exists(lightptname)) + return lightptname; + return ""; + } - // VisualEnvironmentCompiler.Compiler.SyntaxTreeConvertersController возвращает NotSupportedException для RemoteCompiler. Странно... И как это вообще срабатывает? - - var SyntaxTreeConverters = VisualEnvironmentCompiler.Compiler.SyntaxTreeConvertersController.SyntaxTreeConverters; - // Если осталось с прошлого раза - SyntaxTreeConverters.RemoveAll(st => st.Name == "TeacherContolConverter"); - //if (System.IO.File.Exists(FullLightPTName)) // Если в папке есть файл lightpt.dat + public /*async*/ void TryLogin(string login, string pass) + { + var answer = User.Login("", login, pass); + if (answer.Result == "Success") { - //SyntaxTreeConverters.Add(new TeacherContolConverter()); + loginForm.ChangeControlsAfterLogin(login); + } + } + + public bool IsMechmath() => System.Environment.MachineName.ToLower().StartsWith("mil8a-"); + + public void GetGUI(List MenuItems, List ToolBarItems) + { + // Для студентов: если в рабочем каталоге нет lightpt.dat, то кнопки не появляются + // На самом деле надо еще проверять диск P: - точнее, сетевой диск с определенной меткой (например, в его корне лежит файл auth.dat + // if (!File.Exists(Path.Combine(WorkingDir,'lightpt.dat')) + // return; + // Scan disks + // Find NET disk with auth.dat in root + // if not - return + //var WorkingDirectory = Workbench.VisualEnvironmentCompiler.Compiler.CompilerOptions.SourceFileDirectory; + var LightPTExists = false; + var AuthExists = false; + try + { + // Только на мехмате - проверяю все диски на предмет существования в корне файла auth.dat + if (IsMechmath()) + AuthFileFullName = FullAuthNameFromNETDisk(); + + LightPTExists = FullLightPTName() != ""; + AuthExists = AuthFileFullName != ""; + } + catch (Exception) + { + // Погасили исключение } - //System.IO.File.AppendAllText("d:\\Stmd.txt", string.Join(" ", StandartModules.Select(sm => sm.Name)) + '\n'); - //System.IO.File.AppendAllText("d:\\Stmd.txt", FullLightPTName + " " + DateTime.Now + '\n'); - }*/ + // При запуске иконка плагина показывается + // Мехмат: при наличии auth.dat в корне сетевого диска или при наличии lightpt в текущей папке !!! + // Дома: всегда у тех, у кого установлен плагин + + // При запуске auth.dat ищется + // Мехмат: в корне сетевого диска (только!). Если находится, делается попытка авторизации + // Дома: в текущей папке. Если нет, ищется в папке на уровень выше. Если находится, делается попытка авторизации + + // При ручной авторизации - сохранение + // Мехмат: auth сохраняется в корень сетевого диска + // Дома: auth сохраняется в папке на уровень выше текущей. Если это невозможно, то в текущей папке. + // Если это диск C, то тоже не сохранять и тогда сохранять в текущей + + if ( + (IsMechmath() && (LightPTExists || AuthExists)) || + !IsMechmath() // дома - всегда + ) + { + Item = new PluginGUIItem(StringsPrefix + "NAME", StringsPrefix + "DESCRIPTION", loginForm.PluginImage.Image, loginForm.PluginImage.BackColor, Execute); + MenuItems.Add(Item); + ToolBarItems.Add(Item); + } + } + + public void AfterAddInGUI() + { + menuItem = (ToolStripMenuItem)Item.menuItem; + toolStripButton = (ToolStripButton)Item.toolStripButton; + // Попытка выполнить автоматический вход из информации в auth.dat + // Прочитать логин и хеш пароля в auth.dat + // По идее в БД надо хранить хеш пароля. + // Авторизоваться по этому паролю через БД + // Непонятно, как сделать эту часть асинхронно + + // В AuthFileFullName только auth с сетевого диска. Если он пустой, то для дома попытаться добавить сюда + // текущую папку и потом корневую папку + try { + if (!IsMechmath()) // если дома, то искать auth в текущей папке + { + var WorkingDir = WorkingDirectory(); + + var auth = System.IO.Path.Combine(WorkingDir,"auth.dat"); + // искать auth в текущей папке + if (System.IO.File.Exists(auth)) + AuthFileFullName = auth; + else + { + // искать auth в папке на уровень выше + auth = System.IO.Path.Combine(WorkingDir, "..", "auth.dat"); + if (System.IO.File.Exists(auth)) + AuthFileFullName = auth; + } + } + if (AuthFileFullName != "") + { + var ss = System.IO.File.ReadAllLines(AuthFileFullName); + if (ss.Length >= 2) + { + var login = ss[0]; + var pass = ss[1]; + System.Threading.Tasks.Task.Run(() => TryLogin(login, pass)); + } + } + } + catch (Exception) + { } + } private void RunStartingHandler(string filename) { - /*if (RegisterForm.Registered) { System.IO.File.AppendAllText("d:\\runs.txt", filename + " " + DateTime.Now + '\n'); diff --git a/bin/Lib/LightPT.pas b/bin/Lib/LightPT.pas index e422a00bd..0fa9517c4 100644 --- a/bin/Lib/LightPT.pas +++ b/bin/Lib/LightPT.pas @@ -27,7 +27,7 @@ var TaskResultInfo: string; // доп. информация о результате. Как правило пуста. Или содержит TaskException.Info. Или содержит для Solved и BadSolution информацию о модуле: Robot, Drawman, PT4 TaskException: PTException := new PTException; - WriteInfoCallBack: procedure (name: string; result: TaskStatus; AdditionalInfo: string); + WriteInfoCallBack: procedure (LessonName,TaskName: string; result: TaskStatus; AdditionalInfo: string); LessonName: string := ''; TaskNamesMap := new Dictionary; @@ -218,10 +218,10 @@ procedure CheckInitialOutputSeq(a: sequence of System.Type) := CheckInitialOutpu procedure CheckInitialInputSeq(a: sequence of System.Type) := CheckInitialInput(a.Select(x->object(x)).ToArray); -procedure WriteInfoToLocalDatabase(name: string; result: TaskStatus; AdditionalInfo: string := ''); +procedure WriteInfoToLocalDatabase(LessonName,TaskName: string; result: TaskStatus; AdditionalInfo: string := ''); begin try - System.IO.File.AppendAllText('db.txt', $'{name} {dateTime.Now.ToString(''u'')} {Result.ToString} {AdditionalInfo}' + #10); + System.IO.File.AppendAllText('db.txt', $'{LessonName} {TaskName} {dateTime.Now.ToString(''u'')} {Result.ToString} {AdditionalInfo}' + #10); except on e: Exception do Print(e.Message); @@ -987,7 +987,7 @@ begin end; // Хотелось бы писать в БД для Робота и др. имя задания в Task if WriteInfoCallBack<>nil then - WriteInfoCallBack(TName, TaskResult, TaskResultInfo); + WriteInfoCallBack(LessonName,TName, TaskResult, TaskResultInfo); end; procedure LoadLightPTInfo; @@ -999,12 +999,20 @@ begin if line.Trim = '' then continue; if LessonName = '' then - LessonName := line + LessonName := line.ToWords.First // первое слово else begin var (name1,name2) := Regex.Split(line,'->'); TaskNamesMap[name1.Trim.ToLower] := name2.Trim; end; - + end; + if LessonName = '' then + begin + // Имя текущей папки. Плохо - в lightpt забыли написать имя урока + var ttt := ExtractFileDir(System.Environment.GetCommandLineArgs[0]); + var LastDir := ttt.ToWords(System.IO.Path.DirectorySeparatorChar).LastOrDefault; + // Каталог может содержать пробелы. Брать первое слово + if LastDir<>nil then + LessonName := LastDir.ToWords.First; end; except