Skip to content

Commit 22d5307

Browse files
author
bkraul
committed
Work in progress
1 parent 6dcb3fb commit 22d5307

File tree

4 files changed

+435
-2
lines changed

4 files changed

+435
-2
lines changed

BBCodePlus/BBCodePlus.php

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<?php
2+
require_once( 'core/Parser.php' );
3+
require_once( 'core/BBCodeParser.php' );
4+
require_once( 'core/HTMLParser.php' );
5+
26
class BBCodePlusPlugin extends MantisFormattingPlugin {
3-
47
// placeholders for MantisCoreFormatting values.
58
private $t_html_make_links = OFF;
69
private $t_MantisCoreFormatting_process_text = OFF;
@@ -51,6 +54,7 @@ function csp_headers() {
5154
# relax csp when processing markitup.
5255
if ( ON == plugin_config_get( 'process_markitup' ) ) {
5356
http_csp_add( 'script-src', "'self' 'unsafe-inline' 'unsafe-eval'" );
57+
http_csp_add( 'img-src', "*" );
5458
http_csp_add( 'frame-ancestors', "'self'" );
5559
}
5660
}
@@ -204,12 +208,70 @@ public function formatted( $p_event, $p_string, $p_multiline = TRUE ) {
204208
*/
205209
function string_process_bbcode( $p_string, $p_multiline = TRUE ) {
206210

211+
# TODO: check mantis core formatting and make the necessary adjustments.
212+
# TODO: Make <br/> show up inside <pre> tags.
213+
# Mantis core formatting process texts converts ALL newlines to <br>.
214+
# we need to disable process text and do our own.
207215
$t_change_quotes = FALSE;
208216
if ( ini_get_bool( 'magic_quotes_sybase' ) ) {
209217
$t_change_quotes = TRUE;
210218
ini_set( 'magic_quotes_sybase', FALSE );
211219
}
212220

221+
# ensures that the links will be opened in a new window/tab, so as to not lose the currently displayed issue.
222+
$t_extra_link_tags = 'target="_blank"';
223+
224+
# perform sanitation before parsing.
225+
# escape all html code inside <code> tags.
226+
$p_string = preg_replace_callback('/\[code(.*?)\](.*?)\[\/code\]/imsU', function ($match) { return "[code" . $match[1] . "]" . htmlentities($match[2]) . "[/code]"; }, $p_string);
227+
228+
# if mantis core formatting plugin process text feature is off, then we do our own.
229+
if ( $this->t_MantisCoreFormatting_process_text == OFF ) {
230+
$p_string = string_strip_hrefs( $p_string );
231+
$p_string = string_html_specialchars( $p_string );
232+
//$p_string = string_restore_valid_html_tags( $p_string, $p_multiline );
233+
# process spaces and line breaks
234+
if ( $p_multiline ) {
235+
$p_string = string_preserve_spaces_at_bol( $p_string );
236+
$p_string = string_nl2br( $p_string );
237+
}
238+
}
239+
240+
# instance the BBCode parsing class.
241+
$bbCode = new Genert\BBCode\Parser\BBCodeParser();
242+
243+
# add the BBCodePlus custom parsers and overrides.
244+
# check core/BBCodeParser.php for the default ones.
245+
# any default parser can be overriden here.
246+
$bbCode->addParser('email', '/\[email\]([a-z0-9\-_\.\+]+@[a-z0-9\-]+\.[a-z0-9\-\.]+?)\[\/email\]/is', '<a ' . $t_extra_link_tags . ' href="mailto:$1">$1</a>', '$1');
247+
$bbCode->addParser('email-extra', '/\[email=([a-z0-9\-_\.\+]+@[a-z0-9\-]+\.[a-z0-9\-\.]+?)\](.+?)\[\/email\]/is', '<a ' . $t_extra_link_tags . ' href="mailto:$1">$2</a>', '$1');
248+
$bbCode->addParser('size', '/\[size=([+\-\da-z]+?)\](.+?)\[\/size\]/is', '<span class="bbsize-$1">$2</span>', '$1');
249+
$bbCode->addParser('color', '/\[color=([\#a-z0-9]+?)\](.+?)\[\/color\]/is', '<span class="bbcolor-$1">$2</span>', '$1');
250+
$bbCode->addParser('highlight', '/\[highlight=([\#a-z0-9]+?)\](.+?)\[\/highlight\]/is', '<span class="bbhighlight-$1">$2</span>', '$1');
251+
$bbCode->addParser('left-align', '/\[left\](.*?)\[\/left\]/is', '<div align="left">$1</div>', '$1');
252+
$bbCode->addParser('center-align', '/\[center\](.*?)\[\/center\]/is', '<div align="center">$1</div>', '$1');
253+
$bbCode->addParser('right-align', '/\[right\](.*?)\[\/right\]/is', '<div align="right">$1</div>', '$1');
254+
$bbCode->addParser('justify-align', '/\[justify\](.*?)\[\/justify\]/is', '<div align="justify">$1</div>', '$1');
255+
$bbCode->addParser('table-border', '/\[table=(.*?)\](.*?)\[\/table\]/is', '<table border="$1">$2</table>', '$1');
256+
$bbCode->addParser('code', '/\[code\](.*?)\[\/code\]/imsU', '<pre><code class="language-none">$1</code></pre>', '$1');
257+
$bbCode->addParser('code-lang', '/\[code=(\w+)\](.+)\[\/code\]/imsU', '<pre><code class="language-$1">$2</code></pre>','$1');
258+
$bbCode->addParser('code-lang-ln', '/\[code=(\w+)\ start=([0-9]+)\](.+)\[\/code\]/imsU', '<pre class="line-numbers" data-start="$2"><code class="language-$1">$3</code></pre>', '$1');
259+
260+
/*
261+
$p_string = preg_replace_callback('/\[code=(\w+)\](.+)\[\/code\]/imsU',
262+
create_function('$m', '
263+
return "<pre><code class=\"language-" . strtolower($m[1]) . "\">" . $m[2] . "</code></pre>";
264+
')
265+
, $p_string);
266+
*/
267+
# restore pre/code tags.
268+
#$p_string = $this->restore_pre_code_tags( $p_string, $p_multiline);
269+
270+
# parse the BBCode.
271+
$p_string = $bbCode->parse($p_string);
272+
273+
274+
/*
213275
# restore pre/code tags.
214276
$p_string = $this->restore_pre_code_tags( $p_string, $p_multiline);
215277
@@ -333,7 +395,7 @@ function string_process_bbcode( $p_string, $p_multiline = TRUE ) {
333395
if ( OFF == $this->t_MantisCoreFormatting_process_text ) {
334396
$p_string = string_nl2br($p_string);
335397
}
336-
398+
*/
337399
if ( $t_change_quotes )
338400
ini_set( 'magic_quotes_sybase', TRUE );
339401

BBCodePlus/core/BBCodeParser.php

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
<?php
2+
3+
namespace Genert\BBCode\Parser;
4+
5+
final class BBCodeParser extends Parser
6+
{
7+
protected $parsers = [
8+
'h1' => [
9+
'pattern' => '/\[h1\](.*?)\[\/h1\]/s',
10+
'replace' => '<h1>$1</h1>',
11+
'content' => '$1'
12+
],
13+
'h2' => [
14+
'pattern' => '/\[h2\](.*?)\[\/h2\]/s',
15+
'replace' => '<h2>$1</h2>',
16+
'content' => '$1'
17+
],
18+
'h3' => [
19+
'pattern' => '/\[h3\](.*?)\[\/h3\]/s',
20+
'replace' => '<h3>$1</h3>',
21+
'content' => '$1'
22+
],
23+
'h4' => [
24+
'pattern' => '/\[h4\](.*?)\[\/h4\]/s',
25+
'replace' => '<h4>$1</h4>',
26+
'content' => '$1'
27+
],
28+
'h5' => [
29+
'pattern' => '/\[h5\](.*?)\[\/h5\]/s',
30+
'replace' => '<h5>$1</h5>',
31+
'content' => '$1'
32+
],
33+
'h6' => [
34+
'pattern' => '/\[h6\](.*?)\[\/h6\]/s',
35+
'replace' => '<h6>$1</h6>',
36+
'content' => '$1'
37+
],
38+
'bold' => [
39+
'pattern' => '/\[b\](.*?)\[\/b\]/s',
40+
'replace' => '<b>$1</b>',
41+
'content' => '$1'
42+
],
43+
'italic' => [
44+
'pattern' => '/\[i\](.*?)\[\/i\]/s',
45+
'replace' => '<i>$1</i>',
46+
'content' => '$1'
47+
],
48+
'underline' => [
49+
'pattern' => '/\[u\](.*?)\[\/u\]/s',
50+
'replace' => '<u>$1</u>',
51+
'content' => '$1'
52+
],
53+
'strikethrough' => [
54+
'pattern' => '/\[s\](.*?)\[\/s\]/s',
55+
'replace' => '<s>$1</s>',
56+
'content' => '$1'
57+
],
58+
'quote' => [
59+
'pattern' => '/\[quote\](.*?)\[\/quote\]/s',
60+
'replace' => '<blockquote>$1</blockquote>',
61+
'content' => '$1'
62+
],
63+
'link' => [
64+
'pattern' => '/\[url\](.*?)\[\/url\]/s',
65+
'replace' => '<a href="$1">$1</a>',
66+
'content' => '$1'
67+
],
68+
'namedlink' => [
69+
'pattern' => '/\[url\=(.*?)\](.*?)\[\/url\]/s',
70+
'replace' => '<a href="$1">$2</a>',
71+
'content' => '$2'
72+
],
73+
'image' => [
74+
'pattern' => '/\[img\](.*?)\[\/img\]/s',
75+
'replace' => '<img src="$1">',
76+
'content' => '$1'
77+
],
78+
'orderedlistnumerical' => [
79+
'pattern' => '/\[list=1\](.*?)\[\/list\]/s',
80+
'replace' => '<ol>$1</ol>',
81+
'content' => '$1'
82+
],
83+
'orderedlistalpha' => [
84+
'pattern' => '/\[list=a\](.*?)\[\/list\]/s',
85+
'replace' => '<ol type="a">$1</ol>',
86+
'content' => '$1'
87+
],
88+
'unorderedlist' => [
89+
'pattern' => '/\[list\](.*?)\[\/list\]/s',
90+
'replace' => '<ul>$1</ul>',
91+
'content' => '$1'
92+
],
93+
'listitem' => [
94+
'pattern' => '/\[\*\](.*)/',
95+
'replace' => '<li>$1</li>',
96+
'content' => '$1'
97+
],
98+
'code' => [
99+
'pattern' => '/\[code\](.*?)\[\/code\]/s',
100+
'replace' => '<code>$1</code>',
101+
'content' => '$1'
102+
],
103+
'youtube' => [
104+
'pattern' => '/\[youtube\](.*?)\[\/youtube\]/s',
105+
'replace' => '<iframe width="560" height="315" src="//www.youtube-nocookie.com/embed/$1" frameborder="0" allowfullscreen></iframe>',
106+
'content' => '$1'
107+
],
108+
'sub' => [
109+
'pattern' => '/\[sub\](.*?)\[\/sub\]/s',
110+
'replace' => '<sub>$1</sub>',
111+
'content' => '$1'
112+
],
113+
'sup' => [
114+
'pattern' => '/\[sup\](.*?)\[\/sup\]/s',
115+
'replace' => '<sup>$1</sup>',
116+
'content' => '$1'
117+
],
118+
'small' => [
119+
'pattern' => '/\[small\](.*?)\[\/small\]/s',
120+
'replace' => '<small>$1</small>',
121+
'content' => '$1'
122+
],
123+
'table' => [
124+
'pattern' => '/\[table\](.*?)\[\/table\]/s',
125+
'replace' => '<table>$1</table>',
126+
'content' => '$1',
127+
],
128+
'table-row' => [
129+
'pattern' => '/\[tr\](.*?)\[\/tr\]/s',
130+
'replace' => '<tr>$1</tr>',
131+
'content' => '$1',
132+
],
133+
'table-data' => [
134+
'pattern' => '/\[td\](.*?)\[\/td\]/s',
135+
'replace' => '<td>$1</td>',
136+
'content' => '$1',
137+
],
138+
];
139+
140+
public function stripTags(string $source): string
141+
{
142+
foreach ($this->parsers as $name => $parser) {
143+
$source = $this->searchAndReplace($parser['pattern'] . 'i', $parser['content'], $source);
144+
}
145+
146+
return $source;
147+
}
148+
149+
public function parse(string $source, $caseInsensitive = null): string
150+
{
151+
$caseInsensitive = $caseInsensitive === self::CASE_INSENSITIVE ? true : false;
152+
153+
foreach ($this->parsers as $name => $parser) {
154+
$pattern = ($caseInsensitive) ? $parser['pattern'] . 'i' : $parser['pattern'];
155+
156+
$source = $this->searchAndReplace($pattern, $parser['replace'], $source);
157+
}
158+
159+
return $source;
160+
}
161+
}

0 commit comments

Comments
 (0)