1
0
mirror of https://github.com/phpbb/phpbb.git synced 2025-07-15 14:16:28 +02:00
Files
build
code_sniffer
git-tools
phpBB
adm
assets
cache
config
develop
docs
download
files
images
includes
acp
auth
avatar
cache
captcha
config
controller
cron
db
di
diff
event
extension
feed
groupposition
hook
hooks
lock
log
mcp
notification
php
questionnaire
request
search
style
template
tree
ucp
utf
.htaccess
bbcode.php
class_loader.php
constants.php
datetime.php
error_collector.php
filesystem.php
functions.php
functions_acp.php
functions_admin.php
functions_compatibility.php
functions_compress.php
functions_container.php
functions_content.php
functions_convert.php
functions_database_helper.php
functions_display.php
functions_download.php
functions_install.php
functions_jabber.php
functions_messenger.php
functions_module.php
functions_posting.php
functions_privmsgs.php
functions_profile_fields.php
functions_transfer.php
functions_upload.php
functions_url_matcher.php
functions_user.php
index.htm
json_response.php
message_parser.php
session.php
sphinxapi.php
startup.php
user.php
user_loader.php
install
language
store
styles
.htaccess
app.php
common.php
composer.json
composer.lock
cron.php
faq.php
feed.php
index.php
mcp.php
memberlist.php
posting.php
report.php
search.php
ucp.php
viewforum.php
viewonline.php
viewtopic.php
web.config
tests
travis
.gitignore
.travis.yml
README.md
composer.phar
phpunit.xml.all
phpunit.xml.dist
phpunit.xml.functional
php-phpbb/phpBB/includes/bbcode.php
Joas Schilling 6a3d77d76e [ticket/10844] Add phpbb_root_path to phpbb_style_extension_path_provider
The phpbb_root_path needs to be removed from the style path, before giving
the path to the finder, because the finder prepends it later again and is
therefor unable to find style files when the root path is not ./

PHPBB3-10844
2013-04-12 21:35:06 +02:00

597 lines
16 KiB
PHP

<?php
/**
*
* @package phpBB3
* @copyright (c) 2005 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* BBCode class
* @package phpBB3
*/
class bbcode
{
var $bbcode_uid = '';
var $bbcode_bitfield = '';
var $bbcode_cache = array();
var $bbcode_template = array();
var $bbcodes = array();
var $template_bitfield;
/**
* Constructor
* Init bbcode cache entries if bitfield is specified
*/
function bbcode($bitfield = '')
{
if ($bitfield)
{
$this->bbcode_bitfield = $bitfield;
$this->bbcode_cache_init();
}
}
/**
* Second pass bbcodes
*/
function bbcode_second_pass(&$message, $bbcode_uid = '', $bbcode_bitfield = false)
{
if ($bbcode_uid)
{
$this->bbcode_uid = $bbcode_uid;
}
if ($bbcode_bitfield !== false)
{
$this->bbcode_bitfield = $bbcode_bitfield;
// Init those added with a new bbcode_bitfield (already stored codes will not get parsed again)
$this->bbcode_cache_init();
}
if (!$this->bbcode_bitfield)
{
// Remove the uid from tags that have not been transformed into HTML
if ($this->bbcode_uid)
{
$message = str_replace(':' . $this->bbcode_uid, '', $message);
}
return;
}
$str = array('search' => array(), 'replace' => array());
$preg = array('search' => array(), 'replace' => array());
$bitfield = new bitfield($this->bbcode_bitfield);
$bbcodes_set = $bitfield->get_all_set();
$undid_bbcode_specialchars = false;
foreach ($bbcodes_set as $bbcode_id)
{
if (!empty($this->bbcode_cache[$bbcode_id]))
{
foreach ($this->bbcode_cache[$bbcode_id] as $type => $array)
{
foreach ($array as $search => $replace)
{
${$type}['search'][] = str_replace('$uid', $this->bbcode_uid, $search);
${$type}['replace'][] = $replace;
}
if (sizeof($str['search']))
{
$message = str_replace($str['search'], $str['replace'], $message);
$str = array('search' => array(), 'replace' => array());
}
if (sizeof($preg['search']))
{
// we need to turn the entities back into their original form to allow the
// search patterns to work properly
if (!$undid_bbcode_specialchars)
{
$message = str_replace(array('&#58;', '&#46;'), array(':', '.'), $message);
$undid_bbcode_specialchars = true;
}
$message = preg_replace($preg['search'], $preg['replace'], $message);
$preg = array('search' => array(), 'replace' => array());
}
}
}
}
// Remove the uid from tags that have not been transformed into HTML
$message = str_replace(':' . $this->bbcode_uid, '', $message);
}
/**
* Init bbcode cache
*
* requires: $this->bbcode_bitfield
* sets: $this->bbcode_cache with bbcode templates needed for bbcode_bitfield
*/
function bbcode_cache_init()
{
global $phpbb_root_path, $phpEx, $config, $user, $phpbb_extension_manager;
if (empty($this->template_filename))
{
$this->template_bitfield = new bitfield($user->style['bbcode_bitfield']);
$style_resource_locator = new phpbb_style_resource_locator();
$style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider(), $phpbb_root_path);
$template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context(), $phpbb_extension_manager);
$style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $template);
$style->set_style();
$template->set_filenames(array('bbcode.html' => 'bbcode.html'));
$this->template_filename = $style_resource_locator->get_source_file_for_handle('bbcode.html');
}
$bbcode_ids = $rowset = $sql = array();
$bitfield = new bitfield($this->bbcode_bitfield);
$bbcodes_set = $bitfield->get_all_set();
foreach ($bbcodes_set as $bbcode_id)
{
if (isset($this->bbcode_cache[$bbcode_id]))
{
// do not try to re-cache it if it's already in
continue;
}
$bbcode_ids[] = $bbcode_id;
if ($bbcode_id > NUM_CORE_BBCODES)
{
$sql[] = $bbcode_id;
}
}
if (sizeof($sql))
{
global $db;
$sql = 'SELECT *
FROM ' . BBCODES_TABLE . '
WHERE ' . $db->sql_in_set('bbcode_id', $sql);
$result = $db->sql_query($sql, 3600);
while ($row = $db->sql_fetchrow($result))
{
// To circumvent replacing newlines with <br /> for the generated html,
// we use carriage returns here. They are later changed back to newlines
$row['bbcode_tpl'] = str_replace("\n", "\r", $row['bbcode_tpl']);
$row['second_pass_replace'] = str_replace("\n", "\r", $row['second_pass_replace']);
$rowset[$row['bbcode_id']] = $row;
}
$db->sql_freeresult($result);
}
foreach ($bbcode_ids as $bbcode_id)
{
switch ($bbcode_id)
{
case 0:
$this->bbcode_cache[$bbcode_id] = array(
'str' => array(
'[/quote:$uid]' => $this->bbcode_tpl('quote_close', $bbcode_id)
),
'preg' => array(
'#\[quote(?:=&quot;(.*?)&quot;)?:$uid\]((?!\[quote(?:=&quot;.*?&quot;)?:$uid\]).)?#ise' => "\$this->bbcode_second_pass_quote('\$1', '\$2')"
)
);
break;
case 1:
$this->bbcode_cache[$bbcode_id] = array(
'str' => array(
'[b:$uid]' => $this->bbcode_tpl('b_open', $bbcode_id),
'[/b:$uid]' => $this->bbcode_tpl('b_close', $bbcode_id),
)
);
break;
case 2:
$this->bbcode_cache[$bbcode_id] = array(
'str' => array(
'[i:$uid]' => $this->bbcode_tpl('i_open', $bbcode_id),
'[/i:$uid]' => $this->bbcode_tpl('i_close', $bbcode_id),
)
);
break;
case 3:
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'#\[url:$uid\]((.*?))\[/url:$uid\]#s' => $this->bbcode_tpl('url', $bbcode_id),
'#\[url=([^\[]+?):$uid\](.*?)\[/url:$uid\]#s' => $this->bbcode_tpl('url', $bbcode_id),
)
);
break;
case 4:
if ($user->optionget('viewimg'))
{
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'#\[img:$uid\](.*?)\[/img:$uid\]#s' => $this->bbcode_tpl('img', $bbcode_id),
)
);
}
else
{
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'#\[img:$uid\](.*?)\[/img:$uid\]#s' => str_replace('$2', '[ img ]', $this->bbcode_tpl('url', $bbcode_id, true)),
)
);
}
break;
case 5:
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'#\[size=([\-\+]?\d+):$uid\](.*?)\[/size:$uid\]#s' => $this->bbcode_tpl('size', $bbcode_id),
)
);
break;
case 6:
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+):$uid\](.*?)\[/color:$uid\]!is' => $this->bbcode_tpl('color', $bbcode_id),
)
);
break;
case 7:
$this->bbcode_cache[$bbcode_id] = array(
'str' => array(
'[u:$uid]' => $this->bbcode_tpl('u_open', $bbcode_id),
'[/u:$uid]' => $this->bbcode_tpl('u_close', $bbcode_id),
)
);
break;
case 8:
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'#\[code(?:=([a-z]+))?:$uid\](.*?)\[/code:$uid\]#ise' => "\$this->bbcode_second_pass_code('\$1', '\$2')",
)
);
break;
case 9:
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'#(\[\/?(list|\*):[mou]?:?$uid\])[\n]{1}#' => "\$1",
'#(\[list=([^\[]+):$uid\])[\n]{1}#' => "\$1",
'#\[list=([^\[]+):$uid\]#e' => "\$this->bbcode_list('\$1')",
),
'str' => array(
'[list:$uid]' => $this->bbcode_tpl('ulist_open_default', $bbcode_id),
'[/list:u:$uid]' => $this->bbcode_tpl('ulist_close', $bbcode_id),
'[/list:o:$uid]' => $this->bbcode_tpl('olist_close', $bbcode_id),
'[*:$uid]' => $this->bbcode_tpl('listitem', $bbcode_id),
'[/*:$uid]' => $this->bbcode_tpl('listitem_close', $bbcode_id),
'[/*:m:$uid]' => $this->bbcode_tpl('listitem_close', $bbcode_id)
),
);
break;
case 10:
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'#\[email:$uid\]((.*?))\[/email:$uid\]#is' => $this->bbcode_tpl('email', $bbcode_id),
'#\[email=([^\[]+):$uid\](.*?)\[/email:$uid\]#is' => $this->bbcode_tpl('email', $bbcode_id)
)
);
break;
case 11:
if ($user->optionget('viewflash'))
{
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'#\[flash=([0-9]+),([0-9]+):$uid\](.*?)\[/flash:$uid\]#' => $this->bbcode_tpl('flash', $bbcode_id),
)
);
}
else
{
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
'#\[flash=([0-9]+),([0-9]+):$uid\](.*?)\[/flash:$uid\]#' => str_replace('$1', '$3', str_replace('$2', '[ flash ]', $this->bbcode_tpl('url', $bbcode_id, true)))
)
);
}
break;
case 12:
$this->bbcode_cache[$bbcode_id] = array(
'str' => array(
'[/attachment:$uid]' => $this->bbcode_tpl('inline_attachment_close', $bbcode_id)
),
'preg' => array(
'#\[attachment=([0-9]+):$uid\]#' => $this->bbcode_tpl('inline_attachment_open', $bbcode_id)
)
);
break;
default:
if (isset($rowset[$bbcode_id]))
{
if ($this->template_bitfield->get($bbcode_id))
{
// The bbcode requires a custom template to be loaded
if (!$bbcode_tpl = $this->bbcode_tpl($rowset[$bbcode_id]['bbcode_tag'], $bbcode_id))
{
// For some reason, the required template seems not to be available, use the default template
$bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl'];
}
else
{
// In order to use templates with custom bbcodes we need
// to replace all {VARS} to corresponding backreferences
// Note that backreferences are numbered from bbcode_match
if (preg_match_all('/\{(URL|LOCAL_URL|EMAIL|TEXT|SIMPLETEXT|INTTEXT|IDENTIFIER|COLOR|NUMBER)[0-9]*\}/', $rowset[$bbcode_id]['bbcode_match'], $m))
{
foreach ($m[0] as $i => $tok)
{
$bbcode_tpl = str_replace($tok, '$' . ($i + 1), $bbcode_tpl);
}
}
}
}
else
{
// Default template
$bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl'];
}
// Replace {L_*} lang strings
$bbcode_tpl = preg_replace('/{L_([A-Z_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $bbcode_tpl);
if (!empty($rowset[$bbcode_id]['second_pass_replace']))
{
// The custom BBCode requires second-pass pattern replacements
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl)
);
}
else
{
$this->bbcode_cache[$bbcode_id] = array(
'str' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl)
);
}
}
else
{
$this->bbcode_cache[$bbcode_id] = false;
}
break;
}
}
}
/**
* Return bbcode template
*/
function bbcode_tpl($tpl_name, $bbcode_id = -1, $skip_bitfield_check = false)
{
static $bbcode_hardtpl = array();
if (empty($bbcode_hardtpl))
{
global $user;
$bbcode_hardtpl = array(
'b_open' => '<span style="font-weight: bold">',
'b_close' => '</span>',
'i_open' => '<span style="font-style: italic">',
'i_close' => '</span>',
'u_open' => '<span style="text-decoration: underline">',
'u_close' => '</span>',
'img' => '<img src="$1" alt="' . $user->lang['IMAGE'] . '" />',
'size' => '<span style="font-size: $1%; line-height: normal">$2</span>',
'color' => '<span style="color: $1">$2</span>',
'email' => '<a href="mailto:$1">$2</a>'
);
}
if ($bbcode_id != -1 && !$skip_bitfield_check && !$this->template_bitfield->get($bbcode_id))
{
return (isset($bbcode_hardtpl[$tpl_name])) ? $bbcode_hardtpl[$tpl_name] : false;
}
if (empty($this->bbcode_template))
{
if (($tpl = file_get_contents($this->template_filename)) === false)
{
trigger_error('Could not load bbcode template', E_USER_ERROR);
}
// replace \ with \\ and then ' with \'.
$tpl = str_replace('\\', '\\\\', $tpl);
$tpl = str_replace("'", "\'", $tpl);
// strip newlines and indent
$tpl = preg_replace("/\n[\n\r\s\t]*/", '', $tpl);
// Turn template blocks into PHP assignment statements for the values of $bbcode_tpl..
$this->bbcode_template = array();
$matches = preg_match_all('#<!-- BEGIN (.*?) -->(.*?)<!-- END (?:.*?) -->#', $tpl, $match);
for ($i = 0; $i < $matches; $i++)
{
if (empty($match[1][$i]))
{
continue;
}
$this->bbcode_template[$match[1][$i]] = $this->bbcode_tpl_replace($match[1][$i], $match[2][$i]);
}
}
return (isset($this->bbcode_template[$tpl_name])) ? $this->bbcode_template[$tpl_name] : ((isset($bbcode_hardtpl[$tpl_name])) ? $bbcode_hardtpl[$tpl_name] : false);
}
/**
* Return bbcode template replacement
*/
function bbcode_tpl_replace($tpl_name, $tpl)
{
global $user;
static $replacements = array(
'quote_username_open' => array('{USERNAME}' => '$1'),
'color' => array('{COLOR}' => '$1', '{TEXT}' => '$2'),
'size' => array('{SIZE}' => '$1', '{TEXT}' => '$2'),
'img' => array('{URL}' => '$1'),
'flash' => array('{WIDTH}' => '$1', '{HEIGHT}' => '$2', '{URL}' => '$3'),
'url' => array('{URL}' => '$1', '{DESCRIPTION}' => '$2'),
'email' => array('{EMAIL}' => '$1', '{DESCRIPTION}' => '$2')
);
$tpl = preg_replace('/{L_([A-Z_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $tpl);
if (!empty($replacements[$tpl_name]))
{
$tpl = strtr($tpl, $replacements[$tpl_name]);
}
return trim($tpl);
}
/**
* Second parse list bbcode
*/
function bbcode_list($type)
{
if ($type == '')
{
$tpl = 'ulist_open_default';
$type = 'default';
}
else if ($type == 'i')
{
$tpl = 'olist_open';
$type = 'lower-roman';
}
else if ($type == 'I')
{
$tpl = 'olist_open';
$type = 'upper-roman';
}
else if (preg_match('#^(disc|circle|square)$#i', $type))
{
$tpl = 'ulist_open';
$type = strtolower($type);
}
else if (preg_match('#^[a-z]$#', $type))
{
$tpl = 'olist_open';
$type = 'lower-alpha';
}
else if (preg_match('#[A-Z]#', $type))
{
$tpl = 'olist_open';
$type = 'upper-alpha';
}
else if (is_numeric($type))
{
$tpl = 'olist_open';
$type = 'decimal';
}
else
{
$tpl = 'olist_open';
$type = 'decimal';
}
return str_replace('{LIST_TYPE}', $type, $this->bbcode_tpl($tpl));
}
/**
* Second parse quote tag
*/
function bbcode_second_pass_quote($username, $quote)
{
// when using the /e modifier, preg_replace slashes double-quotes but does not
// seem to slash anything else
$quote = str_replace('\"', '"', $quote);
$username = str_replace('\"', '"', $username);
// remove newline at the beginning
if ($quote == "\n")
{
$quote = '';
}
$quote = (($username) ? str_replace('$1', $username, $this->bbcode_tpl('quote_username_open')) : $this->bbcode_tpl('quote_open')) . $quote;
return $quote;
}
/**
* Second parse code tag
*/
function bbcode_second_pass_code($type, $code)
{
// when using the /e modifier, preg_replace slashes double-quotes but does not
// seem to slash anything else
$code = str_replace('\"', '"', $code);
switch ($type)
{
case 'php':
// Not the english way, but valid because of hardcoded syntax highlighting
if (strpos($code, '<span class="syntaxdefault"><br /></span>') === 0)
{
$code = substr($code, 41);
}
// no break;
default:
$code = str_replace("\t", '&nbsp; &nbsp;', $code);
$code = str_replace(' ', '&nbsp; ', $code);
$code = str_replace(' ', ' &nbsp;', $code);
$code = str_replace("\n ", "\n&nbsp;", $code);
// keep space at the beginning
if (!empty($code) && $code[0] == ' ')
{
$code = '&nbsp;' . substr($code, 1);
}
// remove newline at the beginning
if (!empty($code) && $code[0] == "\n")
{
$code = substr($code, 1);
}
break;
}
$code = $this->bbcode_tpl('code_open') . $code . $this->bbcode_tpl('code_close');
return $code;
}
}