tmp_27.06.2026
Различия
Показаны различия между двумя версиями страницы.
| Предыдущая версия справа и слеваПредыдущая версияСледующая версия | Предыдущая версия | ||
| tmp_27.06.2026 [2026/06/27 14:46] – [backend/config/salt.php] VladPolskiy | tmp_27.06.2026 [2026/06/27 15:35] (текущий) – VladPolskiy | ||
|---|---|---|---|
| Строка 1: | Строка 1: | ||
| - | ====== Файл менеджер ====== | + | // assets/js/app.js |
| - | ===== 🗺️ Общая архитектурная схема проекта ===== | + | |
| - | < | + | |
| - | [ ПОЛЬЗОВАТЕЛЬ | + | |
| - | │ | + | |
| - | ▼ | + | |
| - | ┌────────────────────────────────────────────────────────┐ | + | |
| - | │ 1. index.php (Главный шлюз приложения) | + | |
| - | │ - Проверяет сессию | + | |
| - | │ - Если первый запуск ➔ перенаправляет на установку │ | + | |
| - | └──────────────────┬─────────────────────────────────────┘ | + | |
| - | │ | + | |
| - | ▼ | + | |
| - | ┌────────────────────────────────────────────────────────┐ | + | |
| - | │ 2. backend/core/initializer.php (Динамический корень) | + | |
| - | │ - Вычисляет APP_ROOT через __DIR__ | + | |
| - | │ - Создает папки: config/, storage/, system_logs/ | + | |
| - | └──────────────────┬─────────────────────────────────────┘ | + | |
| - | │ | + | |
| - | ▼ | + | |
| - | ┌────────────────────────────────────────────────────────┐ | + | |
| - | │ 3. backend/ | + | |
| - | │ - Сверяет IP с config/ | + | |
| - | │ - Бан на месте: die() │ | + | |
| - | └──────────────────┬─────────────────────────────────────┘ | + | |
| - | │ | + | |
| - | | + | |
| - | ▼ (Если не авторизован) | + | |
| - | ┌────────────────────────────────────────┐ ┌──────────────────────────────────────┐ | + | |
| - | │ 4. ЭКРАН АВТОРИЗАЦИИ / ИНИЦИАЛИЗАЦИИ | + | |
| - | │ - Поля: Логин / Пароль | + | |
| - | │ - Скрытое поле: Honeypot (Ловушка) | + | |
| - | │ - Восстановление: | + | |
| - | │ │ │ │ [Имя / Путь] [Релизы ▼] [ZIP] │ │ | + | |
| - | │ backend/ | + | |
| - | │ - Вырезает XSS / Path Traversal | + | |
| - | │ │ │ │ (Имя | Примечание | Дата/ | + | |
| - | │ backend/ | + | |
| - | │ - Хэширует пароли и текст книги | + | |
| - | │ - Генерирует случайный 8-значный ID │ │ │ НИЖНЕЕ ОКНО | + | |
| - | │ - Сортирует и перетасовывает базу | + | |
| - | │ │ │ │ [Лог действий (для админа)] | + | |
| - | │ │ │ ├──────────────────────────────────┤ │ | + | |
| - | │ │ │ │ Динамический текст (Fetch API) │ │ | + | |
| - | │ │ │ └──────────────────────────────────┘ │ | + | |
| - | └────────────────────────────────────────┘ └──────────────────┬───────────────────┘ | + | |
| - | │ | + | |
| - | ▼ (Любое действие) | + | |
| - | | + | |
| - | │ 6. backend/ | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | │ | + | |
| - | ┌───────────────────┴───────────────────┐ | + | |
| - | ▼ (Действия Админа) | + | |
| - | | + | |
| - | │ backend/ | + | |
| - | │ - list.php | + | |
| - | │ - mkdir.php | + | |
| - | │ - delete.php | + | |
| - | | + | |
| - | </code> | + | document.addEventListener(' |
| + | // --- НАДЕЖНОЕ УПРАВЛЕНИЕ МОДАЛКОЙ С ДЕБАГ-МАЯКОМ --- | ||
| + | // --- УПРАВЛЕНИЕ ЗАГРУЗЧИКОМ ПРОЕКТОВ --- | ||
| + | const btnCreateProject | ||
| + | const projectModal | ||
| + | const btnModalCancel | ||
| + | const btnModalSubmit | ||
| + | const newProjectName | ||
| + | const modalErrorBox | ||
| + | |||
| + | const folderInput | ||
| + | const btnSelectFolder | ||
| + | const folderStatus | ||
| - | ===== 🧩 Карта маскировки | + | if (btnCreateProject && projectModal) { |
| - | Поскольку мы закладываем параноидальную защиту, вот схема того, как скрыты наши | + | |
| + | // Функция проверки условий для активации кнопки "Загрузить" | ||
| + | function checkInputsValidity() { | ||
| + | const nameVal = newProjectName.value.trim(); | ||
| + | const hasFiles = folderInput.files && folderInput.files.length > 0; | ||
| + | |||
| + | if (nameVal !== "" | ||
| + | btnModalSubmit.disabled = false; // Включаем кнопку | ||
| + | btnModalSubmit.style.opacity = " | ||
| + | } else { | ||
| + | btnModalSubmit.disabled = true; // Выключаем кнопку | ||
| + | btnModalSubmit.style.opacity = " | ||
| + | } | ||
| + | } | ||
| - | < | + | |
| - | backend/config/ | + | |
| - | │ | + | |
| - | ├── salt.php | + | // Клик по кастомной кнопке -> триггерим скрытый |
| - | │ | + | btnSelectFolder.addEventListener(' |
| - | │ (Хакер в коде видит только шум, роли замаскированы) | + | |
| - | │ | + | }); |
| - | ├── email.php ───► | + | |
| - | │ (Спрятан от парсеров, | + | // Следим за тем, что пользователь выбрал папку на ПК |
| - | │ | + | folderInput.addEventListener(' |
| - | ├── ip_blacklist.txt | + | if (this.files && this.files.length > 0) { |
| - | │ | + | // Берем имя корневой папки, которую |
| - | └── users.json | + | const firstFile = this.files[0]; |
| - | | + | const rootFolderName = firstFile.webkitRelativePath.split('/' |
| - | │ ID: 85910432 | + | folderStatus.innerHTML = `Выбрано файлов: < |
| - | │ Пароль: $2y$10$... (Защищенный хэш) | + | } else { |
| - | │ Роль: x7R9wQ2pM4zL1vK8 (Случайный шум) │ | + | folderStatus.textContent = "Папка не выбрана"; |
| - | | + | } |
| - | | + | checkInputsValidity(); |
| + | }); | ||
| + | |||
| + | // Открытие модалки | ||
| + | btnCreateProject.addEventListener(' | ||
| + | | ||
| + | | ||
| + | folderStatus.textContent = " | ||
| + | if (modalErrorBox) modalErrorBox.classList.add(' | ||
| + | | ||
| + | btnModalSubmit.style.opacity = " | ||
| + | projectModal.classList.remove(' | ||
| + | newProjectName.focus(); | ||
| + | }); | ||
| + | |||
| + | // Отмена | ||
| + | btnModalCancel.addEventListener(' | ||
| + | projectModal.classList.add(' | ||
| + | }); | ||
| + | |||
| + | // Нажатие | ||
| + | btnModalSubmit.addEventListener(' | ||
| + | const projectName = newProjectName.value.trim(); | ||
| + | if (modalErrorBox) modalErrorBox.classList.add(' | ||
| + | |||
| + | const formData = new FormData(); | ||
| + | formData.append(' | ||
| + | |||
| + | // КРИТИЧЕСКИ ВАЖНО: Пакуем файлы вместе с их путями вложения | ||
| + | for (let i = 0; i < folderInput.files.length; | ||
| + | let file = folderInput.files[i]; | ||
| + | formData.append(' | ||
| + | // Передаем бэкенду относительный | ||
| + | formData.append(' | ||
| + | } | ||
| + | |||
| + | // Меняем статус кнопки на время | ||
| + | btnModalSubmit.disabled = true; | ||
| + | btnModalSubmit.textContent = " | ||
| + | |||
| + | try { | ||
| + | const response = await fetch(' | ||
| + | method: ' | ||
| + | body: formData | ||
| + | }); | ||
| + | const result = await response.json(); | ||
| + | |||
| + | if (result.success) { | ||
| + | projectModal.classList.add(' | ||
| + | btnModalSubmit.textContent = "Загрузить"; | ||
| + | location.reload(); | ||
| + | } else { | ||
| + | btnModalSubmit.disabled = false; | ||
| + | btnModalSubmit.textContent = "Загрузить"; | ||
| + | if (modalErrorBox) { | ||
| + | modalErrorBox.textContent = result.error; | ||
| + | modalErrorBox.classList.remove(' | ||
| + | } | ||
| + | } | ||
| + | } catch (error) { | ||
| + | // Возвращаем кнопку в исходное рабочее состояние | ||
| + | btnModalSubmit.disabled = false; | ||
| + | btnModalSubmit.textContent = " | ||
| + | |||
| + | // КРАСИВО ВЫВОДИМ ОШИБКУ СЕТИ В ТВОЮ ПЛАШКУ БЕЗ ВСЯКИХ АЛЕРТОВ | ||
| + | if (modalErrorBox) { | ||
| + | | ||
| + | modalErrorBox.classList.remove(' | ||
| + | } | ||
| + | } | ||
| + | }); | ||
| + | } | ||
| - | </ | ||
| - | ===== 📂 Карта песочницы на диске (storage/) ===== | ||
| - | Абсолютно безликая структура. Никаких названий компаний и имен. Только цифровые идентификаторы, | ||
| - | < | ||
| - | storage/ | ||
| - | │ | ||
| - | ├── 85910432/ | ||
| - | │ | ||
| - | │ | ||
| - | │ │ | ||
| - | │ | ||
| - | │ | ||
| - | │ | ||
| - | │ | ||
| - | │ | ||
| - | │ | ||
| - | │ │ | ||
| - | │ | ||
| - | │ | ||
| - | ├── 10294811/ | ||
| - | │ | ||
| - | │ | ||
| - | └── system_logs/ | ||
| - | ├── admins_activity.log | ||
| - | └── app_errors.log | ||
| - | </ | ||
| - | ===== Создаем файл backend/ | ||
| - | Этот файл использует магические константы PHP и глобальные массивы сервера, | ||
| - | < | ||
| - | </ | ||
| - | ===== test ===== | ||
| - | // assets/ | ||
| - | document.addEventListener(' | ||
| - | const releasesDropdown = document.getElementById(' | ||
| - | const btnDownloadZip | ||
| - | const filesList | ||
| - | const textEditor | ||
| - | const tabButtons | ||
| // Локальное хранилище для текстов текущего выбранного релиза, | // Локальное хранилище для текстов текущего выбранного релиза, | ||
| Строка 221: | Строка 218: | ||
| }); | }); | ||
| }); | }); | ||
| + | |||
| + | |||
tmp_27.06.2026.1782560760.txt.gz · Последнее изменение: — VladPolskiy
