Страница 1 из 1

Вставка таблиц в форуме phpBB 3

СообщениеДобавлено: 23 дек 2014, 23:07
Александр
Меня давно возмущало в движке форума phpBB отсутствие возможности вставлять html-таблицы в сообщения.
Теоретически можно реализовать это при помощи bb-тегов, чему можно найти примеры в интернете, либо попадались даже советы просто разрешить html-код в сообщениях!
Но у всех этих вариантов слишком много минуов. Например, если задействовать пользовательские bb-теги, то всё равно не будет проверки на корректность вложенности тегов, т. е. возможны конструкции вида:
Код: Выделить всё
[td]текст[/td]текст[table]текст[/table]текст[tr]текст[/tr]
Плюс невозможно реализовать какие-то опциональные параметры типа rowspan, colspan и т. п. — они должны либо быть, либо нет, нужно для каждого варинта (colspan| rowspan| colspan rowspan) свои bb-теги создавать и так во всём, в общем, не удобно.
В поисках по англоязычному интернету самое интересное, что я нашел — это мод [BBCode] Tablemaker v.1.0.0.
Он позволяет через яваскриптовое pop-up окно задать параметры и сгенерировать bb-код таблицы. На мой взгляд его интефейс несколько наворочен, при чём в очень худшую сторону: Зачем простомупользователю задвать такие атрибуты, как cellpadding, cellspacing, высоту таблицы?? А такие нужные атрибуты для ячеек как colspan и rowspan, там не предусмотрены. После тестовой установки этого мода у меня даже не возникло желания попробовать его модернизировать вручную, т. к. пришлось бы переделывать всё, даже сама идея яваскриптового окна, которое при щелчке по родительскому окну браузера уйдёт за него раз и навсегда... она ужасна..
Мод Tablemaker, pop-up окно.

Естественно, этот мод не контролирует правильность вложенности тегов, а bb-код получается неформатированным, просто однородная масса, очень не удобно с таким работать.
Мод Tablemaker, BB-код таблицы.

Я как представил, что предложу пользователям таким макаром таблицы создавать, сам испугался. А неформатирован код потому, что если бы он был отформатирован, то phpBB поставил бы при отображении поста на месте переносов строк теги <br />, например, между рядами таблицы, т. е. получится примерно такая "красота":
Код: Выделить всё
<table><br /><tr><td>...</td><td>...</td></tr><br /><tr><td>...</td><td>...</td></tr><br /></table> и т.д.
Помимо того, что такой код не валиден будет, так и в браузере действительно криво будет.
Просто разрешать html в сообщениях — это с точки зрения безопасности — без комментариев. Наверное, поэтому в движке phpBB и возможности такой даже не предусмотрено. Те кто такое предлагают имею в виду просто отрубить в коде конвертацию html спецсимволов в их эквиваленты-сущности, как сказал выше — это без комментариев.
Разрешить вставку html в сообщения только, например, для администраторов.. И такой вариант иногда встречается. Но, это тоже опасно т. к. администратора могут спровоцировать на цитирование сообщения, в котором будет примерно такой код:
Код: Выделить всё
Бла-бла-бла ну скопируй меня
бла-бла-бла[size=1]<script>alert('XSS')</script>[/size]
Бла-бла-бла, давай, жду ответа с цитатой....
Есть еще вариант разрешить html в сообщениях, но прогонять их через какой-нибудь жесткий чистильщик, например, HTML Purifier.
Тут уже свои нюансы появляются:
Во-первых у HTML Purifier главное достоинство, что он, конечно, вычистит все потенциально опасное из кода, но он пасует перед простыми житейскими проблемами типа лишнего пробела в теге.
HTML Purifier может удалить лишние атрибуты в тегах, лишние символы после имени тега до закрывающей скобки, закрыть незарытый парный тег. Но, например, встретив в таблице такую конструкцию:
Код: Выделить всё
<table>
< tr><td>...</td><td>...</td></tr><tr><td>...</td><td>...</td></tr>
<tr><td>...</td><td>...</td></tr><tr><td>...</td><td>...</td></tr>
</table>
или
<table>
<tr
><td>...</td><td>...</td></tr><tr><td>...</td><td>...</td></tr>
<tr><td>...</td><td>...</td></tr><tr><td>...</td><td>...</td></tr>
</table>
он удалит весь ряд, который начинается с поломанного тега, даже просто, имеющего лишний пробел до имени тега "< tr>". Наверное его можно настроить, чтобы он этого не делал, но честное слово, прочитав документацию и поискав в сети, пока не понял как всё-таки этого добиться, уж очень он тяжеловесный..
Задействовать его имеет смысл, если только мы приняли решение разрешить большое количество html-тегов в сообщении. Валидировать им только таблицы — не самое оптимальное решение, т. к. HTML Purifier требует много ресурсов, а, как писал выше при простых житейских трудностях может спасовать. Т. е. это как из пушки по воробьям палить.
Вообще, HTML Purifier не единственный чистильщик xml/html/css, вот интересный обзор чистильщиков http://htmlpurifier.org/comparison.
В общем, взвесив все эти факторы, я решил, что стоит попробовать реализовать возможность вставки таблиц на форуме в виде html-кода по принципу разрешения тегов и атрибутов из «Белого списка». О чем скоро напишу подробнее..

Re: Вставка таблиц в форуме phpBB 3, моё решение

СообщениеДобавлено: 27 фев 2015, 15:37
Александр
После небольшого перерыва, наконец закончил с модификацией кода форума для создания возможности вставки HTML-таблиц.
Теперь на моём форуме можно вставить в сообщения просто HTML-код таблицы. Парсинг осуществляется по принципу «Белого списка» с заменой совпадений на шаблонные теги.
В общем я примерно месяц потратил чтобы добиться приемлемого результата, особенно меня волновала безопасность!!! Даже не столько XSS-инъекции (вроде замена кода на шаблоны ограждает от них). Больше меня беспокоили SQL-инъекции. Т. к. я не гуру SQL и MySQL, но наслышан про всякие там кавычки и трюки с многобайтовыми символами, который может быть обрезан и после превратиться в ту же кавычку или слэш.ỏ͖͈̞̩͎̻̫̫̜͉̠̫͕̭̭̫̫̹̗̹͈̼̠̖͍͚̥͈̮̼͕̠̤̯̻̥̬̗̼̳̤̳̬̪̹͚̞̼̠͕̼̠̦͚̫͔̯̹͉͉̘͎͕̼̣̝͙̱̟̹̩̟̳̦̭͉̮̖̭̣̣̞̙̗̜̺̭̻̥͚͙̝̦̲̱͉͖͉̰̦͎̫̣̼͎͍̠̮͓̹̹͉̤̰̗̙͕͇͔̱͕̭͈̳̗̭͔̘̖̺̮̜̠͖̘͓̳͕̟̠̱̫̤͓͔̘̰̲͙͍͇̙͎̣̼̗̖͙̯͉̠̟͈͍͕̪͓̝̩̦̖̹̼̠̘̮͚̟͉̺̜͍͓̯̳̱̻͕̣̳͉̻̭̭̱͍̪̩̭̺͕̺̼̥̪͖̦̟͎̻
Я уверен на 99% что я в данном случае утрирую, и сам движок PHPBB 3 хорошо написан в плане санации данных, вводимых в СУБД, да и мой код тоже не особо располагает к хакингу, но всё же я решил исходники модификации здесь пока не выкладывать.

Парсер распознает теги
<table>, </table>, <tbody>, </tbody>, <tr>, </tr>, <th>, </th>, <td>, </td>, вложенные в тег <table>, у которого есть атрибут data-parse.
Т. е. конструкции вида
Код: Выделить всё
<table data-parse>....</table>

Всякие левые атрибуты из тегов удаляются, также удаляется мусор между тегами, где он не допустим.
Но допускается применение к тегу <tаble> классов class="ptab1", class="ptab2", class="ptab3", class="ptab4", class="ptab5"
ptab1 – задает рамку вокруг ячеек "2px solid #4ac;" и выравнивание в ячейках влево
ptab2 – то же самое, но первая ячейка в каждом ряду будет жирной
ptab3 – задает рамку вокруг ячеек "2px solid #4ac;" и выравнивание в ячейках посередине
ptab4 – то же самое, но первая ячейка в каждом ряду будет жирной
ptab5 – рамок у ячеек нет, выравнивание посередине
Если класс не указан – рамок у ячеек нет, выравнивание влево.

Также допускаются атрибуты сolspan и rowspan у тегов <th> и <td>
Таким образом, код вида:
Код: Выделить всё
<table onclick="alert('test')" мусор class="ptab2" class="prosto"
data-parse> мусор <br /> <h1> мусор </h1> <tbody class="ptab2"
><tr>мусор<td мусор onclick='alert("XSS")' сolspan="" rowspan="4">
</table>

Преобразуется в
Код: Выделить всё
<table class="ptab2" data-parse>
<tbody>
<tr>
<td rowspan="4">
</table>

Как видно, вложенность тегов внутри таблицы не проверяется, проверяется только соответствие количества открывающих и закрывающих тегов <tаble> и </tаble>, при несоответствии добавляются нехватающие, это то, что позволяет предотвратить поломку верстки всей страницы.
Валидировать корректность вложенности внутренних тегов было бы уже слишком сложной задачей, и я предпочёл оставить это на откуп пользователю. Если пользователь будет сознательно постоянно вставлять невалидные таблицы, то это уже с ним самим разбираться нужно.

В принципе, мне был интересен сам процесс создания логики парсера, освежить знания по регулярным выражениям. В процессе чтения материалов по валидации на базе регулярных выражений я окончательно понял, что лучше логику сильно не усложнять. Регулярные выражения не годятся для сложной валидации HTML-кода.

Для примера возьмём HTML-код таблицы:
Код: Выделить всё
<table class="data-table-vert" border="0" class="ptab1" data-parse>
<thead>
<tr align="left">
<td class="bdt">Обхват груди, см</td>
<td class="bdt">Обхват талии, см</td>
<td class="bdt">Размер</td>
<td class="bdt">Российский размер</td>
</tr>
</thead>
<tbody>
<tr align="right">
<td class="bdt">86.4</td>
<td class="bdt">71.1</td>
<td class="bdt">S</td>
<td class="bdt">44</td>
</tr>
<tr align="right">
<td class="bdt">91.4</td>
<td class="bdt">73.7</td>
<td class="bdt">S</td>
<td class="bdt">46</td>
</tr>
<tr align="right">
<td class="bdt">96.5</td>
<td class="bdt">76.2</td>
<td class="bdt">M</td>
<td class="bdt">48</td>
</tr>
<tr align="right">
<td class="bdt">101.6</td>
<td class="bdt">83.8</td>
<td class="bdt">M</td>
<td class="bdt">50</td>
</tr>
<tr align="right">
<td class="bdt">106.7</td>
<td class="bdt">86.4</td>
<td class="bdt">L</td>
<td class="bdt">52</td>
</tr>
<tr align="right">
<td class="bdt">111.8</td>
<td class="bdt">91.4</td>
<td class="bdt">L</td>
<td class="bdt">52</td>
</tr>
<tr align="right">
<td class="bdt">116.8</td>
<td class="bdt">94</td>
<td class="bdt">XL</td>
<td class="bdt">54</td>
</tr>
<tr align="right">
<td class="bdt">121.9</td>
<td class="bdt">101.6</td>
<td class="bdt">XL</td>
<td class="bdt">54</td>
</tr>
<tr align="right">
<td class="bdt">127</td>
<td class="bdt">104.1</td>
<td class="bdt">XXL</td>
<td class="bdt">56</td>
</tr>
<tr align="right">
<td class="bdt">132.1</td>
<td class="bdt">109.2</td>
<td class="bdt">XXL</td>
<td class="bdt">56</td>
</tr>
<tr align="right">
<td class="bdt">137.2</td>
<td class="bdt">111.8</td>
<td class="bdt">XXXL</td>
<td class="bdt">58</td>
</tr>
<tr align="right">
<td class="bdt">142.2</td>
<td class="bdt">119.4</td>
<td class="bdt">XXXL</td>
<td class="bdt">58</td>
</tr>
</tbody>
</table>

На выходе получим:
Код: Выделить всё
<table class="ptab1" data-parse>
<tr>
<td>Обхват груди, см</td>
<td>Обхват талии, см</td>
<td>Размер</td>
<td>Российский размер</td>
</tr>
<tbody>
<tr>
<td>86.4</td>
<td>71.1</td>
<td>S</td>
<td>44</td>
</tr>
<tr>
<td>91.4</td>
<td>73.7</td>
<td>S</td>
<td>46</td>
</tr>
<tr>
<td>96.5</td>
<td>76.2</td>
<td>M</td>
<td>48</td>
</tr>
<tr>
<td>101.6</td>
<td>83.8</td>
<td>M</td>
<td>50</td>
</tr>
<tr>
<td>106.7</td>
<td>86.4</td>
<td>L</td>
<td>52</td>
</tr>
<tr>
<td>111.8</td>
<td>91.4</td>
<td>L</td>
<td>52</td>
</tr>
<tr>
<td>116.8</td>
<td>94</td>
<td>XL</td>
<td>54</td>
</tr>
<tr>
<td>121.9</td>
<td>101.6</td>
<td>XL</td>
<td>54</td>
</tr>
<tr>
<td>127</td>
<td>104.1</td>
<td>XXL</td>
<td>56</td>
</tr>
<tr>
<td>132.1</td>
<td>109.2</td>
<td>XXL</td>
<td>56</td>
</tr>
<tr>
<td>137.2</td>
<td>111.8</td>
<td>XXXL</td>
<td>58</td>
</tr>
<tr>
<td>142.2</td>
<td>119.4</td>
<td>XXXL</td>
<td>58</td>
</tr>
</tbody>
</table>

Мне нравится! Только в первом ряду <td> на <th> поменять и ОК.
Конечно, получилось не идеально, и при создании очень навороченных постов с тегами такими, сякими, возможны мелкие проблемы, но, как я писал уже, для меня важнее всего безопасность, а остальное пока устраивает.

А вот примеры применения к тегу <tаble> вышеописанных пяти классов:

Таблица соответствия размеров мужской одежды (Российский размер).


Класс ptab1
Обхват груди, см Обхват талии, см Размер Российский размер
86.4 71.1 S 44
91.4 73.7 S 46
96.5 76.2 M 48
101.6 83.8 M 50
106.7 86.4 L 52
111.8 91.4 L 52
116.8 94 XL 54
121.9 101.6 XL 54
127 104.1 XXL 56
132.1 109.2 XXL 56
137.2 111.8 XXXL 58
142.2 119.4 XXXL 58


Класс ptab2
Обхват груди, см Обхват талии, см Размер Российский размер
86.4 71.1 S 44
91.4 73.7 S 46
96.5 76.2 M 48
101.6 83.8 M 50
106.7 86.4 L 52
111.8 91.4 L 52
116.8 94 XL 54
121.9 101.6 XL 54
127 104.1 XXL 56
132.1 109.2 XXL 56
137.2 111.8 XXXL 58
142.2 119.4 XXXL 58


Класс ptab3
Обхват груди, см Обхват талии, см Размер Российский размер
86.4 71.1 S 44
91.4 73.7 S 46
96.5 76.2 M 48
101.6 83.8 M 50
106.7 86.4 L 52
111.8 91.4 L 52
116.8 94 XL 54
121.9 101.6 XL 54
127 104.1 XXL 56
132.1 109.2 XXL 56
137.2 111.8 XXXL 58
142.2 119.4 XXXL 58


Класс ptab4
Обхват груди, см Обхват талии, см Размер Российский размер
86.4 71.1 S 44
91.4 73.7 S 46
96.5 76.2 M 48
101.6 83.8 M 50
106.7 86.4 L 52
111.8 91.4 L 52
116.8 94 XL 54
121.9 101.6 XL 54
127 104.1 XXL 56
132.1 109.2 XXL 56
137.2 111.8 XXXL 58
142.2 119.4 XXXL 58


Таблица соответствия размеров мужской одежды (Английский размер).


Класс ptab4 с атрибутами colspan и rowspan.
Английский размер extra small small medium large extra large extra extra large
Обхват груди дюймы 33-35 36-38 39-41 42-44 45-47 48-50
см 84-89 91,5-96,5 99-104 107-112 114-119,5 122-127
Обхват талии дюймы 27-29 30-32 33-35 36-38 39-41 42-44
см 68,5-74 76-81 84-89 91,5-96,5 99-104 107-112

Таблица соответствия размеров мужской обуви.


Класс ptab5
Сантиметры 25.5 26 26.5 27 27.5 28 28.5 29 29.5 30 31 32
Россия 39.5 40 40.5 41 41.5 42 42.5 43 43.5 44 45 46
США 7.5 8 8.5 9 9.5 10 10.5 11 11.5 12 13 14
Великобритания 7 7.5 8 8.5 9 9.5 10 10.5 11 11.5 12 13
Европа 40.5 41 41.5 42 42.5 43 43.5 44 44.5 45 46 47