main · Главный модуль 26.750.0 Заметное

Main 26.750.0: точка в имени плейсхолдера больше не ломает почтовые шаблоны

5 мин чтения
Узнавайте о ломающих изменениях Битрикса раньше, чем они доедут до прода: свежие разборы — в канале @bxmax_updates

Main 26.750.0 меняет три файла ядра, +16/−5 строк, и заметная правка среди них одна (вторая, в лицензионном ActivationSystem, служебная). Но сидит она в месте, где из почтового шаблона генерируется PHP-код, так что посмотреть на неё стоит всем, у кого в шаблонах есть плейсхолдеры с точкой в имени, вроде #ORDER.ID#.

Проверьте шаблоны с точкой в именах

Исправлена ветка Bitrix\Main\Mail\Internal\EventMessageTable::replaceTemplateToPhp(), которая превращает текст шаблона в PHP. Метод находит плейсхолдеры по маске /#([0-9a-zA-Z_.]+?)#/ (точка в имени разрешена), а потом подставляет найденные имена в две регулярки: в общую альтернативу, по которой ищет теги, и в паттерн для замены повторов. Имена попадали туда как есть, без экранирования. А точка в регулярке совпадает с одним любым однобайтовым символом, кроме перевода строки (модификаторов s и u у этих паттернов нет).

Тег, который встречается в шаблоне больше одного раза, метод заменяет по одному вхождению через preg_replace(…, 1). Неэкранированный паттерн /#ORDER.ID#/ цеплял и #ORDER_ID#, так что если тот стоял в тексте раньше, первая замена доставалась ему:

        <?php declare(strict_types=1);

use Bitrix\Main\Mail\Internal\EventMessageTable;

echo EventMessageTable::replaceTemplateToPhp(
    'Заказ #ORDER_ID#, код #ORDER.ID#, ещё раз код #ORDER.ID#'
);

    
        до 26.750.0: Заказ <?=$arParams["ORDER.ID"];?>, код <?=$arParams["ORDER.ID"];?>, ещё раз код #ORDER.ID#
с 26.750.0:  Заказ <?=$arParams["ORDER_ID"];?>, код <?=$arParams["ORDER.ID"];?>, ещё раз код <?=$arParams["ORDER.ID"];?>

    

До обновления на место #ORDER_ID# в письмо шло значение ORDER.ID, а последний #ORDER.ID# доходил до получателя сырым.

В общей альтернативе неэкранированная точка мешала, только если на её месте в тексте стоял символ вне маски. Рядом с #ORDER.ID# фрагмент #ORDER"ID# превращался в $arParams["ORDER"ID"], и eval сгенерированного кода падал с ParseError. Теги, которые сами проходят маску, вроде #ORDERXID#, здесь и раньше разбирались верно, потому что имя метод берёт из найденного текста.

Что поменяли в методе:

  • имена плейсхолдеров при сборке альтернативы проходят через preg_quote($k, '/');
  • список имён чистится array_unique(), и повторяющийся плейсхолдер больше не добавляет одинаковые ветки (в комментарии к коду это объяснено экономией лимита компиляции PCRE);
  • появилась страховка: найденный тег, который не проходит проверку /^[0-9a-zA-Z_.]+\z/, пропускается и в PHP-литерал не попадает. В коде это названо «defence in depth», и пока работает экранирование, до этой ветки дело не дойдёт;
  • во второй части метода, где заменяются повторяющиеся теги, паттерн для preg_replace теперь тоже строится через preg_quote.

Для шаблонов без точек в именах результат конвертации прежний, кроме шаблонов, где один плейсхолдер повторяется тысячи раз: там старая регулярка не компилировалась («regular expression is too large») и не срабатывала ни одна подстановка, а благодаря array_unique() теперь срабатывают. В шаблонах с именами вида #A.B# повторяющийся тег, перед которым стоит похожий тег, теперь заменяется во всех местах, #A_B# перед ним больше не получает чужое значение, а фрагмент вроде #A"B# остаётся текстом. Но всё это касается только заново собранного MESSAGE_PHP, а старый лежит в БД, пока шаблон не пересохранят.

Мелочи и находки

  • Правка чинит регулярки, собранные из неэкранированных имён плейсхолдеров. Имена берутся из текста самого шаблона, а в шаблоне и так можно писать <? ?> (метод отдельно отслеживает эти теги), и MESSAGE_PHP исполняется через eval (EventMessageThemeCompiler.php:383, по коду в эталоне). Объяснения есть только в комментариях к коду. Новой возможности выполнить код правка не закрывает: автор шаблона и раньше мог вставить <? ?>.
  • Комментарии к правкам подробные и на английском, при том что остальной EventMessageTable.php почти не комментирован.
  • Четыре «изменённые сигнатуры» в Bitrix\Main\UpdateSystem\ActivationSystem (activateByHash, applyLicenseInfo, reincarnate, sendInfoToPartner) оказались ложной тревогой. Файл обфусцирован, его пересобрали, и у параметров новые случайные имена; типы и число аргументов те же. Логика при этом всё же поменялась: если раскодировать строки обфускатора на обоих снапшотах, в applyLicenseInfo() видна новая ветка. Когда в ответе сервера лицензий есть BI_CONSTRUCTOR_DATE, значение пишется в опцию main / ~bi_constructor_expired_at, рядом с давней парой R7_SERVER_DATE → ~UT_custom_servers_expired_at.
  • В version.php заодно расставили пробелы после запятых в define. Версия собрана 27 августа (SM_VERSION_DATE).
  • Deprecated, новых API и изменений в БД нет.

Что делать

Публичный API не тронут. Если в почтовых шаблонах есть плейсхолдеры с точкой в имени, пересохраните эти шаблоны в админке или через EventMessageTable::update($id, ['MESSAGE' => $message]). По коду в эталоне MESSAGE_PHP хранится в БД и пересобирается только при сохранении MESSAGE (onBeforeUpdate/onBeforeAdd, EventMessageTable.php:252,270) или когда поле пустое (EventMessageCompiler.php:131–139). Без пересохранения письма так и собираются из старого MESSAGE_PHP, поэтому тестовое письмо отправляйте уже после него и сравнивайте с тем, что уходило раньше.

Новая версия вышла — разбор уже в Telegram

В канале @bxmax_updates публикуем каждый свежий разбор: что сломается, что устарело и что появилось в API. Узнаете до того, как обновите прод.

Подписаться

Читайте дальше

main 26.800.0 Безопасность Свежее

Main 26.800.0: закрыт SSRF через ftp://, а translit и выбор SMTP-отправителя работают иначе

Main 26.800.0 закрывает SSRF в `CFile::MakeFileArray()` через ссылки `ftp://` и в RSS-гаджете, а заодно чистит ввод при инлайн-редактировании в `CAdminUiList` и в `menu_edit.php`. Сильнее по проектам ударят изменения поведения: `CUtil::translit()` оставляет на конце `_`, почта по-другому выбирает SM…

1 мин
main 26.700.0 Заметное

Main 26.700.0: в ядре появились фича-флаги

Битрикс выкатил main 26.700.0 — и это тот редкий случай, когда в ядре появляется целая новая подсистема: фича-флаги `Bitrix\Main\Config\Feature` с двумя таблицами в БД. Плюс несколько тихих поведенческих изменений, которые стоит проверить, если у вас не-UTF-8 сайт, кастомные фильтры пользователей ил…

4 мин
main 26.650.0 Заметное

main 26.650.0: сброс счётчиков ленты пачкой и превью своих ссылок без похода наружу

Два изменения в ядре, оба — про лишнюю работу, которую система делала на ровном месте. Счётчики живой ленты научились сбрасываться одним вызовом вместо цикла, а превью ссылок перестало ходить HTTP-запросом на собственный портал. Ломающих удалений нет: все правки сигнатур — добавление аргументов с де…

3 мин
timeman 26.350.0 Заметное Свежее

Timeman 26.350.0: план дня пишется в нужную запись, блоки БП возвращают Saved

В timeman 26.350.0 для коробочного Битрикс24 блоки «Сохранить план на день» и «Сохранить отчёт сотрудника за день» из нового конструктора бизнес-процессов научились писать в заданную запись рабочего дня, оставлять Markdown как есть и сообщать, сохранилось ли (у отчёта новые настройки в конструкторе,…

2 мин
Мы используем файлы cookie для улучшения работы сайта. Продолжая использовать сайт, вы соглашаетесь с нашей политикой конфиденциальности.
AI Домовой

AI Домовой История

на связи

пишет…
Нет истории чатов
AI Домовой

Нужна авторизация

Войдите, чтобы задавать вопросы AI Домовому.

Войти