5
* @version $Id: bbcode.php,v 1.114 2007/10/07 10:34:45 naderman Exp $
6
* @copyright (c) 2005 phpBB Group
7
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
14
if (!defined('IN_PHPBB'))
26
var $bbcode_bitfield = '';
27
var $bbcode_cache = array();
28
var $bbcode_template = array();
30
var $bbcodes = array();
32
var $template_bitfield;
33
var $template_filename = '';
37
* Init bbcode cache entries if bitfield is specified
39
function bbcode($bitfield = '')
43
$this->bbcode_bitfield = $bitfield;
44
$this->bbcode_cache_init();
51
function bbcode_second_pass(&$message, $bbcode_uid = '', $bbcode_bitfield = false)
55
$this->bbcode_uid = $bbcode_uid;
58
if ($bbcode_bitfield !== false)
60
$this->bbcode_bitfield = $bbcode_bitfield;
62
// Init those added with a new bbcode_bitfield (already stored codes will not get parsed again)
63
$this->bbcode_cache_init();
66
if (!$this->bbcode_bitfield)
68
// Remove the uid from tags that have not been transformed into HTML
69
if ($this->bbcode_uid)
71
$message = str_replace(':' . $this->bbcode_uid, '', $message);
77
$str = array('search' => array(), 'replace' => array());
78
$preg = array('search' => array(), 'replace' => array());
80
$bitfield = new bitfield($this->bbcode_bitfield);
81
$bbcodes_set = $bitfield->get_all_set();
83
$undid_bbcode_specialchars = false;
84
foreach ($bbcodes_set as $bbcode_id)
86
if (!empty($this->bbcode_cache[$bbcode_id]))
88
foreach ($this->bbcode_cache[$bbcode_id] as $type => $array)
90
foreach ($array as $search => $replace)
92
${$type}['search'][] = str_replace('$uid', $this->bbcode_uid, $search);
93
${$type}['replace'][] = $replace;
96
if (sizeof($str['search']))
98
$message = str_replace($str['search'], $str['replace'], $message);
99
$str = array('search' => array(), 'replace' => array());
102
if (sizeof($preg['search']))
104
// we need to turn the entities back into their original form to allow the
105
// search patterns to work properly
106
if (!$undid_bbcode_specialchars)
108
$message = str_replace(array(':', '.'), array(':', '.'), $message);
109
$undid_bbcode_specialchars = true;
112
$message = preg_replace($preg['search'], $preg['replace'], $message);
113
$preg = array('search' => array(), 'replace' => array());
119
// Remove the uid from tags that have not been transformed into HTML
120
$message = str_replace(':' . $this->bbcode_uid, '', $message);
126
* requires: $this->bbcode_bitfield
127
* sets: $this->bbcode_cache with bbcode templates needed for bbcode_bitfield
129
function bbcode_cache_init()
131
global $user, $phpbb_root_path;
133
if (empty($this->template_filename))
135
$this->template_bitfield = new bitfield($user->theme['bbcode_bitfield']);
136
$this->template_filename = $phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template/bbcode.html';
138
if (!@file_exists($this->template_filename))
140
trigger_error('The file ' . $this->template_filename . ' is missing.', E_USER_ERROR);
144
$bbcode_ids = $rowset = $sql = array();
146
$bitfield = new bitfield($this->bbcode_bitfield);
147
$bbcodes_set = $bitfield->get_all_set();
149
foreach ($bbcodes_set as $bbcode_id)
151
if (isset($this->bbcode_cache[$bbcode_id]))
153
// do not try to re-cache it if it's already in
156
$bbcode_ids[] = $bbcode_id;
158
if ($bbcode_id > NUM_CORE_BBCODES)
169
FROM ' . BBCODES_TABLE . '
170
WHERE ' . $db->sql_in_set('bbcode_id', $sql);
171
$result = $db->sql_query($sql, 3600);
173
while ($row = $db->sql_fetchrow($result))
175
// To circumvent replacing newlines with <br /> for the generated html,
176
// we use carriage returns here. They are later changed back to newlines
177
$row['bbcode_tpl'] = str_replace("\n", "\r", $row['bbcode_tpl']);
178
$row['second_pass_replace'] = str_replace("\n", "\r", $row['second_pass_replace']);
180
$rowset[$row['bbcode_id']] = $row;
182
$db->sql_freeresult($result);
185
foreach ($bbcode_ids as $bbcode_id)
190
$this->bbcode_cache[$bbcode_id] = array(
192
'[/quote:$uid]' => $this->bbcode_tpl('quote_close', $bbcode_id)
195
'#\[quote(?:="(.*?)")?:$uid\]((?!\[quote(?:=".*?")?:$uid\]).)?#ise' => "\$this->bbcode_second_pass_quote('\$1', '\$2')"
201
$this->bbcode_cache[$bbcode_id] = array(
203
'[b:$uid]' => $this->bbcode_tpl('b_open', $bbcode_id),
204
'[/b:$uid]' => $this->bbcode_tpl('b_close', $bbcode_id),
210
$this->bbcode_cache[$bbcode_id] = array(
212
'[i:$uid]' => $this->bbcode_tpl('i_open', $bbcode_id),
213
'[/i:$uid]' => $this->bbcode_tpl('i_close', $bbcode_id),
219
$this->bbcode_cache[$bbcode_id] = array(
221
'#\[url:$uid\]((.*?))\[/url:$uid\]#s' => $this->bbcode_tpl('url', $bbcode_id),
222
'#\[url=([^\[]+?):$uid\](.*?)\[/url:$uid\]#s' => $this->bbcode_tpl('url', $bbcode_id),
228
if ($user->optionget('viewimg'))
230
$this->bbcode_cache[$bbcode_id] = array(
232
'#\[img:$uid\](.*?)\[/img:$uid\]#s' => $this->bbcode_tpl('img', $bbcode_id),
238
$this->bbcode_cache[$bbcode_id] = array(
240
'#\[img:$uid\](.*?)\[/img:$uid\]#s' => str_replace('$2', '[ img ]', $this->bbcode_tpl('url', $bbcode_id, true)),
247
$this->bbcode_cache[$bbcode_id] = array(
249
'#\[size=([\-\+]?\d+):$uid\](.*?)\[/size:$uid\]#s' => $this->bbcode_tpl('size', $bbcode_id),
255
$this->bbcode_cache[$bbcode_id] = array(
257
'!\[color=(#[0-9a-f]{6}|[a-z\-]+):$uid\](.*?)\[/color:$uid\]!is' => $this->bbcode_tpl('color', $bbcode_id),
263
$this->bbcode_cache[$bbcode_id] = array(
265
'[u:$uid]' => $this->bbcode_tpl('u_open', $bbcode_id),
266
'[/u:$uid]' => $this->bbcode_tpl('u_close', $bbcode_id),
272
$this->bbcode_cache[$bbcode_id] = array(
274
'#\[code(?:=([a-z]+))?:$uid\](.*?)\[/code:$uid\]#ise' => "\$this->bbcode_second_pass_code('\$1', '\$2')",
280
$this->bbcode_cache[$bbcode_id] = array(
282
'#(\[\/?(list|\*):[mou]?:?$uid\])[\n]{1}#' => "\$1",
283
'#(\[list=([^\[]+):$uid\])[\n]{1}#' => "\$1",
284
'#\[list=([^\[]+):$uid\]#e' => "\$this->bbcode_list('\$1')",
287
'[list:$uid]' => $this->bbcode_tpl('ulist_open_default', $bbcode_id),
288
'[/list:u:$uid]' => $this->bbcode_tpl('ulist_close', $bbcode_id),
289
'[/list:o:$uid]' => $this->bbcode_tpl('olist_close', $bbcode_id),
290
'[*:$uid]' => $this->bbcode_tpl('listitem', $bbcode_id),
291
'[/*:$uid]' => $this->bbcode_tpl('listitem_close', $bbcode_id),
292
'[/*:m:$uid]' => $this->bbcode_tpl('listitem_close', $bbcode_id)
298
$this->bbcode_cache[$bbcode_id] = array(
300
'#\[email:$uid\]((.*?))\[/email:$uid\]#is' => $this->bbcode_tpl('email', $bbcode_id),
301
'#\[email=([^\[]+):$uid\](.*?)\[/email:$uid\]#is' => $this->bbcode_tpl('email', $bbcode_id)
307
if ($user->optionget('viewflash'))
309
$this->bbcode_cache[$bbcode_id] = array(
311
'#\[flash=([0-9]+),([0-9]+):$uid\](.*?)\[/flash:$uid\]#' => $this->bbcode_tpl('flash', $bbcode_id),
317
$this->bbcode_cache[$bbcode_id] = array(
319
'#\[flash=([0-9]+),([0-9]+):$uid\](.*?)\[/flash:$uid\]#' => str_replace('$1', '$3', str_replace('$2', '[ flash ]', $this->bbcode_tpl('url', $bbcode_id, true)))
326
$this->bbcode_cache[$bbcode_id] = array(
328
'[/attachment:$uid]' => $this->bbcode_tpl('inline_attachment_close', $bbcode_id)
331
'#\[attachment=([0-9]+):$uid\]#' => $this->bbcode_tpl('inline_attachment_open', $bbcode_id)
337
if (isset($rowset[$bbcode_id]))
339
if ($this->template_bitfield->get($bbcode_id))
341
// The bbcode requires a custom template to be loaded
342
if (!$bbcode_tpl = $this->bbcode_tpl($rowset[$bbcode_id]['bbcode_tag'], $bbcode_id))
344
// For some reason, the required template seems not to be available, use the default template
345
$bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl'];
349
// In order to use templates with custom bbcodes we need
350
// to replace all {VARS} to corresponding backreferences
351
// Note that backreferences are numbered from bbcode_match
352
if (preg_match_all('/\{(URL|LOCAL_URL|EMAIL|TEXT|SIMPLETEXT|IDENTIFIER|COLOR|NUMBER)[0-9]*\}/', $rowset[$bbcode_id]['bbcode_match'], $m))
354
foreach ($m[0] as $i => $tok)
356
$bbcode_tpl = str_replace($tok, '$' . ($i + 1), $bbcode_tpl);
364
$bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl'];
367
// Replace {L_*} lang strings
368
$bbcode_tpl = preg_replace('/{L_([A-Z_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $bbcode_tpl);
370
if (!empty($rowset[$bbcode_id]['second_pass_replace']))
372
// The custom BBCode requires second-pass pattern replacements
373
$this->bbcode_cache[$bbcode_id] = array(
374
'preg' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl)
379
$this->bbcode_cache[$bbcode_id] = array(
380
'str' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl)
386
$this->bbcode_cache[$bbcode_id] = false;
394
* Return bbcode template
396
function bbcode_tpl($tpl_name, $bbcode_id = -1, $skip_bitfield_check = false)
398
static $bbcode_hardtpl = array();
399
if (empty($bbcode_hardtpl))
403
$bbcode_hardtpl = array(
404
'b_open' => '<span style="font-weight: bold">',
405
'b_close' => '</span>',
406
'i_open' => '<span style="font-style: italic">',
407
'i_close' => '</span>',
408
'u_open' => '<span style="text-decoration: underline">',
409
'u_close' => '</span>',
410
'img' => '<img src="$1" alt="' . $user->lang['IMAGE'] . '" />',
411
'size' => '<span style="font-size: $1%; line-height: normal">$2</span>',
412
'color' => '<span style="color: $1">$2</span>',
413
'email' => '<a href="mailto:$1">$2</a>'
417
if ($bbcode_id != -1 && !$skip_bitfield_check && !$this->template_bitfield->get($bbcode_id))
419
return (isset($bbcode_hardtpl[$tpl_name])) ? $bbcode_hardtpl[$tpl_name] : false;
422
if (empty($this->bbcode_template))
424
if (($tpl = file_get_contents($this->template_filename)) === false)
426
trigger_error('Could not load bbcode template', E_USER_ERROR);
429
// replace \ with \\ and then ' with \'.
430
$tpl = str_replace('\\', '\\\\', $tpl);
431
$tpl = str_replace("'", "\'", $tpl);
433
// strip newlines and indent
434
$tpl = preg_replace("/\n[\n\r\s\t]*/", '', $tpl);
436
// Turn template blocks into PHP assignment statements for the values of $bbcode_tpl..
437
$this->bbcode_template = array();
439
$matches = preg_match_all('#<!-- BEGIN (.*?) -->(.*?)<!-- END (?:.*?) -->#', $tpl, $match);
441
for ($i = 0; $i < $matches; $i++)
443
if (empty($match[1][$i]))
448
$this->bbcode_template[$match[1][$i]] = $this->bbcode_tpl_replace($match[1][$i], $match[2][$i]);
452
return (isset($this->bbcode_template[$tpl_name])) ? $this->bbcode_template[$tpl_name] : ((isset($bbcode_hardtpl[$tpl_name])) ? $bbcode_hardtpl[$tpl_name] : false);
456
* Return bbcode template replacement
458
function bbcode_tpl_replace($tpl_name, $tpl)
462
static $replacements = array(
463
'quote_username_open' => array('{USERNAME}' => '$1'),
464
'color' => array('{COLOR}' => '$1', '{TEXT}' => '$2'),
465
'size' => array('{SIZE}' => '$1', '{TEXT}' => '$2'),
466
'img' => array('{URL}' => '$1'),
467
'flash' => array('{WIDTH}' => '$1', '{HEIGHT}' => '$2', '{URL}' => '$3'),
468
'url' => array('{URL}' => '$1', '{DESCRIPTION}' => '$2'),
469
'email' => array('{EMAIL}' => '$1', '{DESCRIPTION}' => '$2')
472
$tpl = preg_replace('/{L_([A-Z_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $tpl);
474
if (!empty($replacements[$tpl_name]))
476
$tpl = strtr($tpl, $replacements[$tpl_name]);
483
* Second parse list bbcode
485
function bbcode_list($type)
489
$tpl = 'ulist_open_default';
492
else if ($type == 'i')
495
$type = 'lower-roman';
497
else if ($type == 'I')
500
$type = 'upper-roman';
502
else if (preg_match('#^(disc|circle|square)$#i', $type))
505
$type = strtolower($type);
507
else if (preg_match('#^[a-z]$#', $type))
510
$type = 'lower-alpha';
512
else if (preg_match('#[A-Z]#', $type))
515
$type = 'upper-alpha';
517
else if (is_numeric($type))
520
$type = 'arabic-numbers';
525
$type = 'arabic-numbers';
528
return str_replace('{LIST_TYPE}', $type, $this->bbcode_tpl($tpl));
532
* Second parse quote tag
534
function bbcode_second_pass_quote($username, $quote)
536
// when using the /e modifier, preg_replace slashes double-quotes but does not
537
// seem to slash anything else
538
$quote = str_replace('\"', '"', $quote);
539
$username = str_replace('\"', '"', $username);
541
// remove newline at the beginning
547
$quote = (($username) ? str_replace('$1', $username, $this->bbcode_tpl('quote_username_open')) : $this->bbcode_tpl('quote_open')) . $quote;
553
* Second parse code tag
555
function bbcode_second_pass_code($type, $code)
557
// when using the /e modifier, preg_replace slashes double-quotes but does not
558
// seem to slash anything else
559
$code = str_replace('\"', '"', $code);
564
// Not the english way, but valid because of hardcoded syntax highlighting
565
if (strpos($code, '<span class="syntaxdefault"><br /></span>') === 0)
567
$code = substr($code, 41);
573
$code = str_replace("\t", ' ', $code);
574
$code = str_replace(' ', ' ', $code);
575
$code = str_replace(' ', ' ', $code);
577
// remove newline at the beginning
578
if (!empty($code) && $code[0] == "\n")
580
$code = substr($code, 1);
585
$code = $this->bbcode_tpl('code_open') . $code . $this->bbcode_tpl('code_close');
b'\\ No newline at end of file'