Старый README сохранён как README.upstream.md.
reg — панель регистрации DMR ID
Небольшой PHP-скрипт для радиолюбительского DMR-сервера (XLX/HBLink, узел DMRYKT). Решает одну задачу: выдача и учёт локальных DMR ID. Радиолюбитель заполняет заявку с позывным и контактом в Telegram, скрипт присваивает свободный ID из диапазона 1410000–1419999 и кладёт заявку в очередь. Администратор через веб-админку подтверждает, редактирует, блокирует или удаляет записи, после чего подтверждённые записи выгружаются в файл dmrid.dat формата ID;CALLSIGN;, который читают XLX и Pi-Star.
Базы данных нет: всё хранится в JSON-файле и в текстовом .dat.
Стек
- PHP (процедурный, без фреймворка и без Composer). Версия не определена из кода, но используются стрелочные функции — требуется PHP 7.4+.
- Хранилище:
db.json(структура{"count": N, "results": [...]}) иdmrid.dat(ID;CALLSIGN;построчно). - Frontend: HTML, CSS, ванильный JavaScript (клиентская валидация и AJAX-проверка уникальности).
- Веб-сервер с PHP — по README ожидается размещение в
/var/www/xlxd/regрядом с XLX-сервером. - Внешних API нет.
Структура
| Путь | Назначение |
|---|---|
index.php |
Стартовая страница со ссылками на админку, XLX-сервер и файлы баз |
register.php |
Публичная форма заявки на DMR ID: валидация позывного и Telegram, генерация свободного ID, запись в db.json с confirmed: false |
admin.php |
Админка: HTML, таблица подтверждённых записей, поиск, сортировка, пагинация, форма добавления вручную |
adminLogic.php |
Вся логика админки, подключается первой строкой admin.php. Обрабатывает sync, confirm, block, delete, edit, ajax_check, добавление через POST, а также поиск, сортировку и пагинацию |
check_unique.php |
Отдельный JSON-эндпоинт проверки уникальности ID и позывного по db.json и dmrid.dat |
db.json |
Основная база заявок и записей |
dmrid.dat |
Выгрузка подтверждённых записей для XLX/Pi-Star |
assets/css/style.css |
Стили админки |
assets/js/main.js |
Клиентская валидация формы добавления и AJAX-проверка уникальности |
savedata/ |
Резервная копия предыдущей версии: admin.php, logic.php, db.json (232 записи), dmrid.dat |
README |
Исходное описание структуры проекта от автора |
README.upstream.md |
Исходная инструкция по установке от автора |
Как запустить
Отдельного запуска нет — это набор PHP-файлов, который кладётся в корень веб-сервера. По инструкции автора (README.upstream.md):
git clone <репозиторий> /var/www/xlxd/reg
chmod 666 /var/www/xlxd/reg/db.json
chmod 666 /var/www/xlxd/reg/dmrid.dat
ln -s /var/www/xlxd/reg/dmrid.dat /xlxd/dmrid.dat
Адреса после установки:
- админка —
https://ваш-сайт/reg/ - форма регистрации —
https://ваш-сайт/reg/register.php
Права 666 на файлы данных обязательны: процесс PHP пишет в них напрямую через file_put_contents.
Конфигурация
Файлов конфигурации и переменных окружения нет. Всё, что можно поменять, захардкожено в исходниках:
| Что | Где | Значение |
|---|---|---|
| Пути к файлам данных | adminLogic.php, register.php, check_unique.php |
__DIR__ . '/db.json', __DIR__ . '/dmrid.dat' |
| Диапазон выдаваемых ID | register.php |
rand(1410000, 1419999) |
| Формат позывного | register.php, adminLogic.php |
/^[A-Z0-9]{4,7}$/ |
| Формат Telegram | register.php |
/^[a-zA-Z0-9_]{5,32}$/ |
| Допустимый ID при ручном добавлении | adminLogic.php |
6–7 цифр, от 100000 до 9999999 |
| Записей на страницу | adminLogic.php |
$perPage = 15 |
| Ссылки на внешние ресурсы | index.php, admin.php |
https://xlx.dmrykt.ru/, https://dmrykt.ru/ |
| Путь к стилям | admin.php |
/reg/assets/css/style.css — приложение обязано лежать в подкаталоге /reg |
Состояние
Рабочий, но простой скрипт; развитие остановлено. 8 коммитов, последний — 12.07.2025, из них четыре последних правили только README. Реального кода — один заход «Add files via upload» 11.07.2025.
Функциональность закрыта: заявка, подтверждение, редактирование, блокировка, удаление, синхронизация в .dat, поиск, сортировка, пагинация. db.json и dmrid.dat в репозитории пустые — боевые данные вычищены, но в savedata/ лежит старый снимок на 232 записи.
Что не доделано
- Админка полностью открыта. В
admin.phpиadminLogic.phpнет ни аутентификации, ни проверки сессии, ни CSRF-токенов. Любой, кто знает адрес, может добавлять, редактировать, блокировать и удалять записи обычными GET-запросами видаadmin.php?delete=1410001. Прикрывать доступ нужно на уровне веб-сервера (basic auth или ограничение по IP). - Нет блокировок при записи.
file_get_contents+file_put_contentsбезflock: две одновременные заявки могут затереть друг друга. - Обработчик
editвadminLogic.phpдублирует работу: сначала точечно правит строку вdmrid.dat, а следом полностью перезаписывает файл из всех записейdb.json— включая неподтверждённые. Это расходится с логикойsync, которая пишет только подтверждённые. - В
check_unique.phpразборdb.jsonидёт по верхнему уровню (foreach ($json as $entry)), а не по$json['results']— проверка по JSON-базе фактически не работает. Этот файл к тому же дублируетajax_checkизadminLogic.phpи, судя по коду фронтенда, не вызывается. - Сравнение
$item['id'] === $confirmIdстрогое, а ID вdb.jsonможет оказаться строкой — тогда подтверждение и блокировка молча ничего не сделают. - В
admin.phpв шапке таблицы (<thead>) используется$row['id']вне цикла — обращение к неопределённой переменной. - Сообщения об ошибках выводятся без
htmlspecialcharsвregister.php, хотя тексты и константные. - Заявки принимаются без капчи и без ограничения частоты — форма открыта для спама.
- В
README.upstream.mdуказан адрес кошелька USDT (TRC20) для донатов — при публикации репозитория стоит решить, нужен ли он там. - В
savedata/db.jsonлежат персональные данные пользователей: позывные, имена, фамилии, города и Telegram-контакты 232 человек. Перед тем как делать репозиторий публичным, этот файл лучше убрать. - Тестов нет, CI нет, логирования действий администратора нет.