Большое обновление GUI интерфейс

Большое обновление GUI интерфейс

- Добавлен фраемворr Walles
- Удалена консольная версия
- Проработан интерфейс и дизайн
- Добавлено кеширование для быстрой реакции.
- Сделан .ps1 сборщик для удобной сборки проекта.
- Обновлён Readme
This commit is contained in:
2025-11-14 08:40:25 +07:00
parent 752f294392
commit 02ae56b78c
93 changed files with 7477 additions and 3504 deletions

View File

@@ -4,7 +4,7 @@ import (
"fmt"
"os/exec"
"path/filepath"
"strconv"
"syscall"
"time"
config "vServer/Backend/config"
tools "vServer/Backend/tools"
@@ -14,6 +14,11 @@ var mysqlProcess *exec.Cmd
var mysql_status bool = false
var mysql_secure bool = false
// GetMySQLStatus возвращает статус MySQL
func GetMySQLStatus() bool {
return mysql_status
}
var mysqldPath string
var configPath string
var dataDirAbs string
@@ -86,16 +91,8 @@ func StartMySQLServer(secure bool) {
mysql_port = config.ConfigData.Soft_Settings.Mysql_port
mysql_ip = config.ConfigData.Soft_Settings.Mysql_host
if tools.Port_check("MySQL", mysql_ip, strconv.Itoa(mysql_port)) {
return
}
if mysql_status {
tools.Logs_file(1, "MySQL", "Сервер MySQL уже запущен", "logs_mysql.log", true)
return
}
if false {
tools.Logs_file(1, "MySQL", "Сервер MySQL уже запущен", "logs_mysql.log", false)
return
}
@@ -105,9 +102,9 @@ func StartMySQLServer(secure bool) {
// Выбор сообщения
if secure {
tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в режиме безопасности", "logs_mysql.log", true)
tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в режиме безопасности", "logs_mysql.log", false)
} else {
tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в обычном режиме", "logs_mysql.log", true)
tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в обычном режиме", "logs_mysql.log", false)
}
// Общая логика запуска
@@ -115,7 +112,7 @@ func StartMySQLServer(secure bool) {
mysqlProcess.Dir = binDirAbs
tools.Logs_console(mysqlProcess, console_mysql)
tools.Logs_file(0, "MySQL", fmt.Sprintf("Сервер MySQL запущен на %s:%d", mysql_ip, mysql_port), "logs_mysql.log", true)
tools.Logs_file(0, "MySQL", fmt.Sprintf("Сервер MySQL запущен на %s:%d", mysql_ip, mysql_port), "logs_mysql.log", false)
mysql_status = true
@@ -124,22 +121,30 @@ func StartMySQLServer(secure bool) {
// StopMySQLServer останавливает MySQL сервер
func StopMySQLServer() {
if mysql_status {
cmd := exec.Command("taskkill", "/F", "/IM", "mysqld.exe")
err := cmd.Run()
tools.CheckError(err)
tools.Logs_file(0, "MySQL", "Сервер MySQL остановлен", "logs_mysql.log", true)
mysql_status = false
} else {
tools.Logs_file(1, "MySQL", "Сервер MySQL уже остановлен", "logs_mysql.log", true)
if !mysql_status {
return // Уже остановлен
}
// Сначала пробуем завершить процесс корректно
if mysqlProcess != nil && mysqlProcess.Process != nil {
mysqlProcess.Process.Kill()
mysqlProcess = nil
}
// Дополнительно убиваем все mysqld.exe процессы
cmd := exec.Command("taskkill", "/F", "/IM", "mysqld.exe")
// Скрываем окно taskkill
cmd.SysProcAttr = &syscall.SysProcAttr{
HideWindow: true,
CreationFlags: 0x08000000,
}
cmd.Run()
tools.Logs_file(0, "MySQL", "Сервер MySQL остановлен", "logs_mysql.log", false)
mysql_status = false
}
func ResetPasswordMySQL() {

View File

@@ -1,195 +0,0 @@
package webserver
import (
"fmt"
"os"
"time"
admin "vServer/Backend/admin"
config "vServer/Backend/config"
tools "vServer/Backend/tools"
)
var Secure_post bool = false
func CommandListener() {
fmt.Println("Введите help для получения списка команд")
fmt.Println("")
for {
var cmd string
fmt.Print(tools.Color(" > ", tools.Оранжевый))
fmt.Scanln(&cmd)
switch cmd {
case "help":
fmt.Println(" ------------------------------------------")
fmt.Println(" 1: mysql_stop - Остановить MySQL")
fmt.Println(" 2: mysql_start - Запустить MySQL")
fmt.Println(" 3: mysql_pass - Сбросить пароль MySQL")
fmt.Println(" 4: clear - Очистить консоль")
fmt.Println(" 5: cert_reload - Перезагрузить SSL сертификаты")
fmt.Println(" 6: admin_toggle - Переключить режим админки (embed/файловая система)")
fmt.Println(" 7: config_reload - Перезагрузить конфигурацию")
fmt.Println(" 8: restart - Перезапустить сервер")
fmt.Println(" 9: php_console - Открыть PHP консоль")
fmt.Println(" 10: exit - выйти из программы")
fmt.Println(" ------------------------------------------")
fmt.Println("")
case "mysql_stop":
StopMySQLServer()
case "mysql_start":
StartMySQLServer(false)
case "mysql_pass":
ResetPasswordMySQL()
case "clear":
ClearConsole()
case "cert_reload":
ReloadCertificates()
case "admin_toggle":
AdminToggle()
case "config_reload":
ConfigReload()
case "restart":
RestartServer()
case "time_run":
fmt.Println(tools.ServerUptime("get"))
case "secure_post":
if Secure_post {
Secure_post = false
fmt.Println("Secure post is disabled")
} else {
Secure_post = true
fmt.Println("Secure post is enabled")
}
case "exit":
fmt.Println("Завершение...")
os.Exit(0)
default:
fmt.Println(" Неизвестная команда. Введите 'help' для получения списка команд")
fmt.Println("")
}
}
}
func RestartServer() {
fmt.Println("")
fmt.Println("⏹️ Перезагрузка сервера...")
// Останавливаем все сервисы
fmt.Println("⏹️ Останавливаем сервисы...")
fmt.Println("")
// Останавливаем HTTP/HTTPS серверы
StopHTTPServer()
StopHTTPSServer()
// Останавливаем MySQL
if mysql_status {
StopMySQLServer()
time.Sleep(1 * time.Second)
}
// Останавливаем PHP
PHP_Stop()
time.Sleep(1 * time.Second)
fmt.Println("")
fmt.Println("✅ Все сервисы остановлены")
// Перезагружаем конфигурацию
fmt.Println("📋 Перезагружаем конфигурацию...")
fmt.Println("")
config.LoadConfig()
// Запускаем сервисы заново
fmt.Println("🚀 Запускаем сервисы...")
fmt.Println("")
// Запускаем HTTP/HTTPS серверы
go StartHTTP()
time.Sleep(100 * time.Millisecond)
go StartHTTPS()
time.Sleep(100 * time.Millisecond)
// Запускаем PHP
PHP_Start()
time.Sleep(100 * time.Millisecond)
// Запускаем MySQL
StartMySQLServer(false)
time.Sleep(100 * time.Millisecond)
fmt.Println("✅ Сервер успешно перезагружен!")
fmt.Println("")
}
func ClearConsole() {
// Очищаем консоль, но сохраняем первые три строки
fmt.Print("\033[H\033[2J") // ANSI escape code для очистки экрана
println("")
println(tools.Color("vServer", tools.Жёлтый) + tools.Color(" 1.0.0", tools.Голубой))
println(tools.Color("Автор: ", tools.Зелёный) + tools.Color("Суманеев Роман (c) 2025", tools.Голубой))
println(tools.Color("Официальный сайт: ", tools.Зелёный) + tools.Color("https://voxsel.ru", tools.Голубой))
println("")
// Восстанавливаем первые три строки
fmt.Println("Введите help для получения списка команд")
fmt.Println("")
}
// Переключает режим админки между embed и файловой системой
func AdminToggle() {
fmt.Println("")
if admin.UseEmbedded {
// Переключаем на файловую систему
admin.UseEmbedded = false
fmt.Println("🔄 Режим изменен: Embedded → Файловая система")
fmt.Println("✅ Админка переключена на файловую систему")
fmt.Println("📁 Файлы будут загружаться с диска из Backend/admin/html/")
fmt.Println("💡 Теперь можно редактировать файлы и изменения будут видны сразу")
} else {
// Переключаем обратно на embedded
admin.UseEmbedded = true
fmt.Println("🔄 Режим изменен: Файловая система → Embedded")
fmt.Println("✅ Админка переключена на embedded режим")
fmt.Println("📦 Файлы загружаются из встроенных ресурсов")
fmt.Println("🚀 Быстрая загрузка, но изменения требуют перекомпиляции")
}
fmt.Println("")
}
// Перезагружает конфигурацию без перезапуска сервисов
func ConfigReload() {
fmt.Println("")
fmt.Println("📋 Перезагружаем конфигурацию...")
// Загружаем новую конфигурацию
config.LoadConfig()
fmt.Println("✅ Конфигурация успешно перезагружена!")
fmt.Println("💡 Изменения применятся к новым запросам")
fmt.Println("")
}

View File

@@ -4,12 +4,34 @@ import (
"net/http"
"os"
"strings"
"sync"
"vServer/Backend/config"
tools "vServer/Backend/tools"
)
var (
siteStatusCache map[string]bool
statusMutex sync.RWMutex
)
func StartHandler() {
http.HandleFunc("/", handler)
updateSiteStatusCache()
}
func updateSiteStatusCache() {
statusMutex.Lock()
defer statusMutex.Unlock()
siteStatusCache = make(map[string]bool)
for _, site := range config.ConfigData.Site_www {
siteStatusCache[site.Host] = site.Status == "active"
}
}
// UpdateSiteStatusCache - экспортируемая функция для обновления кэша
func UpdateSiteStatusCache() {
updateSiteStatusCache()
}
// Проверка wildcard паттерна для alias
@@ -175,6 +197,17 @@ func checkVAccessAndHandle(w http.ResponseWriter, r *http.Request, filePath stri
return true
}
// Проверяет включен ли сайт (оптимизировано через кэш)
func isSiteActive(host string) bool {
statusMutex.RLock()
defer statusMutex.RUnlock()
if status, exists := siteStatusCache[host]; exists {
return status
}
return false
}
// Обработчик запросов
func handler(w http.ResponseWriter, r *http.Request) {
@@ -187,6 +220,13 @@ func handler(w http.ResponseWriter, r *http.Request) {
return // Если прокси обработал запрос, прерываем выполнение
}
// Проверяем статус сайта
if !isSiteActive(host) {
http.ServeFile(w, r, "WebServer/tools/error_page/index.html")
tools.Logs_file(2, "H503", "🚫 Сайт отключен: "+host, "logs_http.log", false)
return
}
// ЕДИНСТВЕННАЯ ПРОВЕРКА vAccess - простая проверка запрошенного пути
if !checkVAccessAndHandle(w, r, r.URL.Path, host) {
return

View File

@@ -8,6 +8,11 @@ import (
var httpServer *http.Server
var port_http string = "80"
// GetHTTPStatus возвращает статус HTTP сервера
func GetHTTPStatus() bool {
return httpServer != nil
}
// Запуск HTTP сервера
func StartHTTP() {

View File

@@ -18,6 +18,11 @@ var fallbackCert *tls.Certificate
var httpsServer *http.Server
var port_https string = "443"
// GetHTTPSStatus возвращает статус HTTPS сервера
func GetHTTPSStatus() bool {
return httpsServer != nil
}
// Запуск https сервера
func StartHTTPS() {

View File

@@ -13,6 +13,7 @@ import (
"strconv"
"strings"
"sync"
"syscall"
"time"
config "vServer/Backend/config"
tools "vServer/Backend/tools"
@@ -30,6 +31,11 @@ var (
var address_php string
var Сonsole_php bool = false
// GetPHPStatus возвращает статус PHP сервера
func GetPHPStatus() bool {
return len(phpProcesses) > 0 && !stopping
}
// FastCGI константы
const (
FCGI_VERSION_1 = 1
@@ -99,6 +105,12 @@ func startFastCGIWorker(port int, workerID int) {
"PHP_FCGI_MAX_REQUESTS=1000", // Перезапуск после 1000 запросов
)
// Скрываем консольное окно
cmd.SysProcAttr = &syscall.SysProcAttr{
HideWindow: true,
CreationFlags: 0x08000000, // CREATE_NO_WINDOW
}
if !Сonsole_php {
cmd.Stdout = nil
cmd.Stderr = nil
@@ -499,6 +511,10 @@ func PHP_Stop() {
// Дополнительно убиваем все процессы php-cgi.exe
cmd := exec.Command("taskkill", "/F", "/IM", "php-cgi.exe")
cmd.SysProcAttr = &syscall.SysProcAttr{
HideWindow: true,
CreationFlags: 0x08000000,
}
cmd.Run()
tools.Logs_file(0, "PHP", "🛑 Все FastCGI процессы остановлены", "logs_php.log", true)

View File

@@ -21,6 +21,11 @@ func StartHandlerProxy(w http.ResponseWriter, r *http.Request) (valid bool) {
configMutex.RLock()
defer configMutex.RUnlock()
// Проверяем глобальный флаг прокси
if !config.ConfigData.Soft_Settings.Proxy_enabled {
return false
}
// Проходим по всем прокси конфигурациям
for _, proxyConfig := range config.ConfigData.Proxy_Service {
// Пропускаем отключенные прокси

View File

@@ -136,15 +136,21 @@ func findVAccessFiles(requestPath string, host string) []string {
// Базовый путь к сайту (НЕ public_www, а уровень выше)
basePath := "WebServer/www/" + host
// Получаем абсолютный базовый путь
absBasePath, err := tools.AbsPath(basePath)
if err != nil {
return configFiles
}
// Проверяем корневой vAccess.conf
rootConfigPath := filepath.Join(basePath, "vAccess.conf")
rootConfigPath := filepath.Join(absBasePath, "vAccess.conf")
if _, err := os.Stat(rootConfigPath); err == nil {
configFiles = append(configFiles, rootConfigPath)
}
// Разбиваем путь на части для поиска вложенных конфигов
pathParts := strings.Split(strings.Trim(requestPath, "/"), "/")
currentPath := basePath
currentPath := absBasePath
for _, part := range pathParts {
if part == "" {
@@ -439,7 +445,8 @@ func HandleVAccessError(w http.ResponseWriter, r *http.Request, errorPage string
switch {
case errorPage == "404":
// Стандартная 404 страница
http.ServeFile(w, r, "WebServer/tools/error_page/index.html")
errorPagePath, _ := tools.AbsPath("WebServer/tools/error_page/index.html")
http.ServeFile(w, r, errorPagePath)
case strings.HasPrefix(errorPage, "http://") || strings.HasPrefix(errorPage, "https://"):
// Внешний сайт - редирект
@@ -448,11 +455,13 @@ func HandleVAccessError(w http.ResponseWriter, r *http.Request, errorPage string
default:
// Локальный путь от public_www
localPath := "WebServer/www/" + host + "/public_www" + errorPage
if _, err := os.Stat(localPath); err == nil {
http.ServeFile(w, r, localPath)
absLocalPath, _ := tools.AbsPath(localPath)
if _, err := os.Stat(absLocalPath); err == nil {
http.ServeFile(w, r, absLocalPath)
} else {
// Файл не найден - показываем стандартную 404
http.ServeFile(w, r, "WebServer/tools/error_page/index.html")
errorPagePath, _ := tools.AbsPath("WebServer/tools/error_page/index.html")
http.ServeFile(w, r, errorPagePath)
tools.Logs_file(1, "vAccess", "❌ Страница ошибки не найдена: "+localPath, "logs_vaccess.log", false)
}
}
@@ -468,14 +477,21 @@ func CheckProxyVAccess(requestPath string, domain string, r *http.Request) (bool
// Путь к конфигурационному файлу прокси
configPath := "WebServer/tools/Proxy_vAccess/" + domain + "_vAccess.conf"
// Получаем абсолютный путь
absConfigPath, err := tools.AbsPath(configPath)
if err != nil {
// При ошибке получения пути - разрешаем доступ
return true, ""
}
// Проверяем существование файла
if _, err := os.Stat(configPath); os.IsNotExist(err) {
if _, err := os.Stat(absConfigPath); os.IsNotExist(err) {
// Нет конфигурационного файла - разрешаем доступ
return true, ""
}
// Парсим конфигурационный файл
config, err := parseVAccessFile(configPath)
config, err := parseVAccessFile(absConfigPath)
if err != nil {
tools.Logs_file(1, "vAccess-Proxy", "❌ Ошибка парсинга "+configPath+": "+err.Error(), "logs_vaccess_proxy.log", false)
return true, "" // При ошибке парсинга разрешаем доступ
@@ -491,7 +507,8 @@ func HandleProxyVAccessError(w http.ResponseWriter, r *http.Request, errorPage s
case errorPage == "404":
// Стандартная 404 страница
w.WriteHeader(http.StatusForbidden)
http.ServeFile(w, r, "WebServer/tools/error_page/index.html")
errorPagePath, _ := tools.AbsPath("WebServer/tools/error_page/index.html")
http.ServeFile(w, r, errorPagePath)
case strings.HasPrefix(errorPage, "http://") || strings.HasPrefix(errorPage, "https://"):
// Внешний сайт - редирект
@@ -500,6 +517,7 @@ func HandleProxyVAccessError(w http.ResponseWriter, r *http.Request, errorPage s
default:
// Для прокси возвращаем 403 Forbidden
w.WriteHeader(http.StatusForbidden)
http.ServeFile(w, r, "WebServer/tools/error_page/index.html")
errorPagePath, _ := tools.AbsPath("WebServer/tools/error_page/index.html")
http.ServeFile(w, r, errorPagePath)
}
}