pascalabcnet/VisualPlugins/TraningControlPlugin/TeacherControlPlugin.cs
Mikhalkovich Stanislav 2b72dd1142 2026
2026-01-02 12:36:47 +03:00

342 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using VisualPascalABCPlugins.DBAccess;
using PascalABCCompiler;
using System.Linq;
using static System.Net.Mime.MediaTypeNames;
namespace VisualPascalABCPlugins
{
//имя класса *_VisualPascalABCPlugin
public class VisualPascalABCPlugin_TeacherControlPlugin : IExtendedVisualPascalABCPlugin
{
private const string LabelEntered = "Авторизация: ";
private const string LabelNotEntered = "Авторизация: вход не выполнен";
public static string StringsPrefix = "VPP_REGISTER_AND_CONTROL_PLUGIN_";
public static string ServerAddress = "https://air.mmcs.sfedu.ru/pascalabc";
IVisualEnvironmentCompiler VisualEnvironmentCompiler;
IWorkbench Workbench;
//private TeacherControlForm RegisterForm = new TeacherControlForm(); // старая форма авторизации
//private LoginForm RegisterFormNew = new LoginForm(); // новая форма авторизации
// User
SiteAccessProvider User;
private PluginGUIItem Item;
public string Name { get => "Teacher Control Plugin"; }
public string Version { get => "0.2"; }
public string Copyright { get => "Copyright © 2021-2026 by Stanislav Mikhalkovich"; }
public string Login = null;
public string Password = null;
public LoginForm loginForm;
public ToolStripMenuItem menuItem = null;
public ToolStripButton toolStripButton = null;
// public string AuthFileFullName = "";
public bool IsMechmath;
public VisualPascalABCPlugin_TeacherControlPlugin(IWorkbench Workbench)
{
this.Workbench = Workbench;
VisualEnvironmentCompiler = Workbench.VisualEnvironmentCompiler;
User = new SiteAccessProvider();
if (IsLightPTInWorkingDirectory())
{
IsMechmath = System.Environment.MachineName.ToLower().StartsWith("mil8a-");
// Попытаемся изменить ServerAddress если в папке есть server.dat
TryChangeServerAddress(ref ServerAddress);
User.ServAddr = ServerAddress;
loginForm = new LoginForm(this);
VisualEnvironmentCompiler.ConvertUnitTextProperty = (FileName, Text) =>
{
string fname = Path.GetFileNameWithoutExtension(FileName);
if (fname == "Tasks")
{
int newLinePos = Text.IndexOf('\n');
string firstLine = newLinePos == -1 ? Text : Text.Substring(0, newLinePos);
if (firstLine.Contains("encrypted"))
{
string remainingText = Text.Substring(newLinePos + 1);
Text = TeacherPluginUtils.DecryptString(remainingText);
}
return Text;
}
return Text;
};
}
// RegisterForm.VisualEnvironmentCompiler = VisualEnvironmentCompiler; // Пока форма регистрации никак не связана с компилятором
// Регистрация обработчика
this.Workbench.ServiceContainer.RunService.Starting += RunStartingHandler;
this.Workbench.ServiceContainer.RunService.ChangeArgsBeforeRun += ChangeArgsBeforeRunHandler;
//VisualEnvironmentCompiler.Compiler.SourceFilesProvider = TeacherSourceFilesProvider;
//Workbench.ServiceContainer.BuildService.BeforeCompile += BeforeCompileHandler;
}
public void Execute()
{
loginForm.SiteProvider = User;
loginForm.ShowDialog(); // OK никогда не будет
}
public void AddMessage(string text)
{
Workbench.CompilerConsoleWindow.AddTextToCompilerMessages(text + Environment.NewLine);
}
public void AddMessage(Exception e) => AddMessage(e.ToString());
public string WorkingDirectory()
{
var FileName = Workbench.ServiceContainer.DocumentService.CurrentCodeFileDocument.FileName;
return System.IO.Path.GetDirectoryName(FileName);
}
public string FullLightPTName()
{
var WorkingDir = WorkingDirectory();
var lightptname = Path.Combine(WorkingDir, "lightpt.dat");
if (File.Exists(lightptname))
return lightptname;
return "";
}
public bool IsLightPTInWorkingDirectory()
{
var WorkingDir = WorkingDirectory();
var lightptname = Path.Combine(WorkingDir, "lightpt.dat");
return File.Exists(lightptname);
}
public bool TryChangeServerAddress(ref string ServerAddress)
{
var WorkingDir = WorkingDirectory();
var server_dat_name = Path.Combine(WorkingDir, "server.dat");
if (File.Exists(server_dat_name))
{
try
{
ServerAddress = System.IO.File.ReadAllText(server_dat_name).Trim();
return true;
}
catch
{
return false; // не поменяли ServerName
// погасить исключение
}
}
return false;
}
public /*async*/ void TryLogin(string login, string pass)
{
// Гасим все исключения
try
{
var answer = User.Login("", login, pass);
if (answer.Result == "Success")
{
loginForm.ChangeControlsAfterLogin(login);
var Rating = User.GetRating("", login, pass);
loginForm.SetRating(Rating.Result);
}
}
catch (Exception e)
{
AddMessage(e);
}
}
public string FullAuthNameFromNETDisk()
{
var AuthFileFullName = "";
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))
AuthFileFullName = auth;
}
}
catch (Exception)
{ } // Тут исключение быть не может и даже если, то неинформативно
return AuthFileFullName;
}
public string FullAuthNameFromWorkingDirOrParent()
{
var AuthFileFullName = "";
try
{
var WorkingDir = WorkingDirectory();
var auth = Path.Combine(WorkingDir, "auth.dat");
var exists = false;
if (File.Exists(auth)) // искать auth в текущей папке. Если нет, то
exists = true;
else
{
auth = Path.Combine(WorkingDir, "..", "auth.dat"); // искать auth в папке на уровень выше
if (File.Exists(auth))
exists = true;
}
if (exists) // то в auth - его путь Преобразуем его в полный путь
{
var fi = new System.IO.FileInfo(auth);
AuthFileFullName = fi.FullName;
}
}
catch (Exception)
{ }
return AuthFileFullName;
}
public string CalcAuthFullName()
{
var AuthFileFullName = "";
// На мехмате - проверяю все диски на предмет существования в корне файла auth.dat
if (IsMechmath)
AuthFileFullName = FullAuthNameFromNETDisk();
else // Это домашний компьютер
AuthFileFullName = FullAuthNameFromWorkingDirOrParent();
return AuthFileFullName;
}
public void InitItems(List<IPluginGUIItem> MenuItems, List<IPluginGUIItem> ToolBarItems)
{
Item = new PluginGUIItem(StringsPrefix + "NAME", StringsPrefix + "DESCRIPTION", loginForm.PluginImage.Image, loginForm.PluginImage.BackColor, Execute);
MenuItems.Add(Item);
ToolBarItems.Add(Item);
}
public void GetGUI(List<IPluginGUIItem> MenuItems, List<IPluginGUIItem> 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;
// При ручной авторизации - сохранение
// Мехмат: auth сохраняется в корень сетевого диска
// Дома: auth сохраняется в папке на уровень выше текущей. Если это невозможно, то в текущей папке.
// Если это диск C, то тоже не сохранять и тогда сохранять в текущей
// При запуске кнопки плагина показываются
// Дома: всегда у тех, у кого установлен плагин
// Мехмат: при наличии lightpt в текущей папке или при наличии auth.dat в корне сетевого диска !!!
//if (!IsMechmath) // дома - всегда
// InitItems(MenuItems, ToolBarItems);
//else // это мехмат
// SSM 20/06/22 Решил включить плагин в инсталлят и показывать кнопки только если есть lightpt.dat в текущем
// или auth.dat в корне сетевого - убрал это 11.07.23 - только если при запуске lightpt.dat в текущем!!!
{
if (IsLightPTInWorkingDirectory()) // если lightpt.dat существует в текущем
InitItems(MenuItems, ToolBarItems);
/*else
{
var AuthFileFullName = FullAuthNameFromNETDisk();
if (AuthFileFullName != "") // если auth.dat существует в корне сетевого диска
InitItems(MenuItems, ToolBarItems);
}*/
}
}
public void AfterAddInGUI()
{
if (Item == null) // Если не показали кнопки, то нет смысла в дальнейших действиях - плагин неактивен
{
AddMessage("TeacherControlPlugin deactivated"); // Не выполнено условие LightPTExists || AuthExists
return;
}
menuItem = (ToolStripMenuItem)Item.menuItem;
toolStripButton = (ToolStripButton)Item.toolStripButton;
// При запуске auth.dat ищется и делается попытка авторизации:
// Мехмат: в корне сетевого диска (только!). Если находится, делается попытка авторизации
// Дома: в текущей папке. Если нет, ищется в папке на уровень выше. Если находится, делается попытка авторизации
// При этом на мехмате не ищется lightpt.dat в текущем
// Версия. Разрешить на мехмате автоматически авторизоваться если заходим из папки с lightpt.dat
// А если его нет, то ищем auth в корне сетевого
// Последовательность поиска auth.dat на мехмате:
// В текущем, на уровень выше (только если в текущем есть lightpt) и на сетевом
try
{
// Попытка автоматического входа
// AuthFileFullName для мехмата был запомнен в GetGUI
// SSM 11/07/23 - нет, AuthFileFullName для мехмата отдельно теперь не перевычисляется для простоты!!!
// Нет - только на мехмате. Заполнить если дома!!!
// Думаю, здесь всё надо перевычислить. Начать с текущего, потом на уровень выше и потом в корень сетевого диска
// !!! НАДО ТУТ ИСКАТЬ lightpt.dat в текущем!!!
var AuthFileFullName = "";
if (IsLightPTInWorkingDirectory()) // Только если lightPT.dat в текущем, ищем auth.dat в текущем или выше
AuthFileFullName = FullAuthNameFromWorkingDirOrParent();
/*if (AuthFileFullName == "" && IsMechmath)
{
AuthFileFullName = FullAuthNameFromNETDisk();
}*/
if (AuthFileFullName != "")
{
//var ss = File.ReadAllLines(AuthFileFullName);
var ss = TeacherPluginUtils.ReadLoginPassFromAuth(AuthFileFullName);
if (ss.Length >= 2)
{
var login = ss[0];
var pass = ss[1];
// В TryLogin может быть исключение, которое не перехватывается этим кодом, т.к.в другом потоке
System.Threading.Tasks.Task.Run(() => TryLogin(login, pass));
}
}
}
catch (Exception e)
{
AddMessage(e); // И тут уже вывести причину. Она только в ReadLoginPassFromAuth может быть
}
}
private void RunStartingHandler(string filename)
{
}
private void ChangeArgsBeforeRunHandler(ref string args)
{
if (Item == null) // если нет кнопок с человечком, то в глобальную базу писаться не будет в принципе!
return;
args += " " + loginForm.Authorized.ToString();
if (loginForm.Authorized) // Параметр Текст программы добавляется только если зарегистрирован
{
var FileName = Workbench.ServiceContainer.DocumentService.CurrentCodeFileDocument.FileName;
var text = Workbench.VisualEnvironmentCompiler.StandartCompiler.GetSourceFileText(FileName);
if (text.Length > 5000)
text = text.Substring(0, 5000);
text = text.Replace("\\\"", "\\ \"");
text = text.Replace("\"", "\\\"");
args += " " + "\"" + text + "\"";
}
}
}
}