Уличная репутация: я работал на Infopop (позже известный как Groupee, теперь Social Strata), создателей UBBCode, вещи, которая была скопирована и преобразована в просто старый обычный «BBCode».
tl; dr: Время написать собственный синтаксический анализатор без регулярных выражений.
Большинство анализаторов BBCode используют регулярные выражения, и это работает в большинстве случаев, но здесь вы делаете что-то свое. Простые старые регулярные выражения вам не помогут. Регулярные выражения имеют два режима работы, которые мешают нам: мы можем либо сопоставить все между двумя тегами в «жадном» режиме, либо в «не жадном» режиме.
В «жадном» режиме мы будем фиксировать все, что находится между самым первым открывающим заданием и самым последним закрывающим тегом. Это ужасно ломает вещи. Возьмите этот случай:
[a][b][c]...[/c][/b][/a]...[a]...[/a]
Жадное регулярное выражение типа \[a\].+\[/a\]
собирается захватить все от первого открывающего тега до этого последнего закрывающего тега, игнорируя тот факт, что доводчик не закрывает открывающее устройство.
Другой вариант хуже. Возьмите этот случай:
[a][b][a]...[/a][/b][/a]
Неудобное регулярное выражение типа \[a\].+?\[/a\]
(единственное изменение - знак вопроса) будет соответствовать первому открывающему тегу, но затем оно будет соответствовать первому закрывающему тегу, снова игнорируя, что закрывающий тег не принадлежит открывающий тег.
Способ, который я решил таким образом, еще в первобытные дни, полностью игнорировал тот факт, что открывающие и закрывающие теги не совпадали. Я просто зацикливал всю цепочку регулярных выражений преобразования тегов, пока вывод не перестал изменяться Это было просто и эффективно, главным образом потому, что доступный набор тегов был преднамеренно ограничен, поэтому вложение никогда не было проблемой.
В тот момент, когда вы разрешаете вложение одинаковых меток, слепая, грубая сила больше не является подходящим инструментом.
Если ни один из механизмов синтаксического анализа BBCode там не будет работать для вас, вам, возможно, придется написать свой собственный. Проверьте все из них. Есть некоторые на PEAR, есть расширение PECL и т. Д. Также проверьте другие языки для вдохновения, CPAN в Perl имеет дюжину различных реализаций, некоторые из которых очень мощные и сложные (если в этом миксе нет подходящего синтаксического анализатора рекурсивного спуска Буду в депрессии). Это хороший вызов, но это не так сложно. С другой стороны, я написал как пять сейчас (ни один из которых я не могу выпустить), так что, может быть, я пристрастен?
Начните с разрыва строки на [
и ]
. Просмотрите полученный массив, отслеживая, когда индекс массива после открывающей скобки и до следующей закрывающей скобки выглядит как действительный тег и / или атрибуты. Вам нужно будет подумать о том, что происходит, когда атрибут может содержать скобки, или, что еще хуже, являются URL-адресами с большими скобками (например, синтаксис PHP-массива). Вам также необходимо подумать об атрибутах в целом, в том числе о том, как (если?) Они заключаются в кавычки, если допускается несколько атрибутов для каждого тега (как в вашем примере), и что делать с недопустимыми атрибутами.
Поскольку вы продолжаете обрабатывать строку, вам также необходимо отслеживать, какие теги открыты и в каком порядке. Вам придется подумать о том, какие теги разрешены внутри других тегов. Вам также придется иметь дело с неправильным вложением, например [a][b][/a][/b]
. Ваши варианты будут либо повторно открывать внутренний тег после закрытия внешнего, либо закрывать внутренний, как только внешний делает. Хуже того, различное поведение может иметь смысл в зависимости от ситуации. Хуже того, такие дурацкие теги, как [*]
внутри [list]
, которые традиционно не имеют закрывающего тега!
Как только вы обработали строку и создали список открывающих и закрывающих тегов (и, возможно, повторно уравновешивали открывающиеся и закрывающиеся теги), вы можете преобразовать результат в HTML, или каким-либо другим образом полученным результатом. Это когда и как вы должны переместить вывод этих конкретных тегов в конец нового документа.
Как только вы закончите, напишите тысячу тестов.Попробуйте разбить его, разбить на мелкие кусочки, создать уязвимости XSS и сделать все возможное, чтобы ваша жизнь стала адом.Это будет стоить того, потому что результатом будет механизм BBCode, который будет делать то, что вы пытаетесь сделать.