mirror of
https://github.com/phpbb/phpbb.git
synced 2025-07-31 22:10:45 +02:00
[ticket/11768] This commit integrates s9e\TextFormatter
This commit integrates s9e\TextFormatter as outlined in http://area51.phpbb.com/phpBB/viewtopic.php?f=108&t=44467 PHPBB3-11768
This commit is contained in:
37
phpBB/phpbb/textformatter/cache.php
Normal file
37
phpBB/phpbb/textformatter/cache.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\textformatter;
|
||||
|
||||
/**
|
||||
* text_formatter.cache service
|
||||
*
|
||||
* Currently only used to signal that something that could effect the rendering has changed.
|
||||
* BBCodes, smilies, censored words, templates, etc...
|
||||
*
|
||||
* @todo functionality should be moved to data_access
|
||||
*
|
||||
* @package phpBB3
|
||||
*/
|
||||
interface cache
|
||||
{
|
||||
/**
|
||||
* Invalidate and/or regenerate this text formatter's cache(s)
|
||||
*/
|
||||
public function invalidate();
|
||||
|
||||
/**
|
||||
* Tidy/prune this text formatter's cache(s)
|
||||
*/
|
||||
public function tidy();
|
||||
}
|
233
phpBB/phpbb/textformatter/data_access.php
Normal file
233
phpBB/phpbb/textformatter/data_access.php
Normal file
@@ -0,0 +1,233 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\textformatter;
|
||||
|
||||
/**
|
||||
* text_formatter.data_access service
|
||||
*
|
||||
* Data access layer that fetchs BBCodes, smilies and censored words from the database.
|
||||
* To be extended to include insert/update/delete operations.
|
||||
*
|
||||
* Also used to get templates.
|
||||
*
|
||||
* @package phpBB3
|
||||
*/
|
||||
class data_access
|
||||
{
|
||||
/**
|
||||
* @var string Name of the BBCodes table
|
||||
*/
|
||||
protected $bbcodes_table;
|
||||
|
||||
/**
|
||||
* @var phpbb_db_driver
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* @var string Name of the smilies table
|
||||
*/
|
||||
protected $smilies_table;
|
||||
|
||||
/**
|
||||
* @var string Name of the styles table
|
||||
*/
|
||||
protected $styles_table;
|
||||
|
||||
/**
|
||||
* @var string Path to the styles dir
|
||||
*/
|
||||
protected $styles_path;
|
||||
|
||||
/**
|
||||
* @var string Name of the words table
|
||||
*/
|
||||
protected $words_table;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \phpbb\db\driver\driver_interface $db Database connection
|
||||
* @param string $bbcodes_table Name of the BBCodes table
|
||||
* @param string $smilies_table Name of the smilies table
|
||||
* @param string $styles_table Name of the styles table
|
||||
* @param string $words_table Name of the words table
|
||||
* @param string $styles_path Path to the styles dir
|
||||
* @return null
|
||||
*/
|
||||
public function __construct(\phpbb\db\driver\driver_interface $db, $bbcodes_table, $smilies_table, $styles_table, $words_table, $styles_path)
|
||||
{
|
||||
$this->db = $db;
|
||||
|
||||
$this->bbcodes_table = $bbcodes_table;
|
||||
$this->smilies_table = $smilies_table;
|
||||
$this->styles_table = $styles_table;
|
||||
$this->words_table = $words_table;
|
||||
|
||||
$this->styles_path = $styles_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of custom BBCodes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_bbcodes()
|
||||
{
|
||||
$sql = 'SELECT bbcode_match, bbcode_tpl FROM ' . $this->bbcodes_table;
|
||||
$result = $this->db->sql_query($sql);
|
||||
$rows = $this->db->sql_fetchrowset($result);
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of smilies
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_smilies()
|
||||
{
|
||||
// NOTE: smilies that are displayed on the posting page are processed first because they're
|
||||
// typically the most used smilies and it ends up producing a slightly more efficient
|
||||
// renderer
|
||||
$sql = 'SELECT code, emotion, smiley_url, smiley_width, smiley_height
|
||||
FROM ' . $this->smilies_table . '
|
||||
ORDER BY display_on_posting DESC';
|
||||
$result = $this->db->sql_query($sql);
|
||||
$rows = $this->db->sql_fetchrowset($result);
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of installed styles
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_styles()
|
||||
{
|
||||
$sql = 'SELECT style_id, style_path, bbcode_bitfield FROM ' . $this->styles_table;
|
||||
$result = $this->db->sql_query($sql);
|
||||
$rows = $this->db->sql_fetchrowset($result);
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bbcode.html template for every installed style
|
||||
*
|
||||
* @return array 2D array. style_id as keys, each element is an array with a "template" element that contains the style's bbcode.html and a "bbcodes" element that contains the name of each BBCode that is to be stylised
|
||||
*/
|
||||
public function get_styles_templates()
|
||||
{
|
||||
$templates = array();
|
||||
|
||||
$bbcode_ids = array(
|
||||
'quote' => 0,
|
||||
'b' => 1,
|
||||
'i' => 2,
|
||||
'url' => 3,
|
||||
'img' => 4,
|
||||
'size' => 5,
|
||||
'color' => 6,
|
||||
'u' => 7,
|
||||
'code' => 8,
|
||||
'list' => 9,
|
||||
'*' => 9,
|
||||
'email' => 10,
|
||||
'flash' => 11,
|
||||
'attachment' => 12,
|
||||
);
|
||||
|
||||
$styles = array();
|
||||
foreach ($this->get_styles() as $row)
|
||||
{
|
||||
$styles[$row['style_id']] = $row;
|
||||
}
|
||||
|
||||
foreach ($styles as $style_id => $style)
|
||||
{
|
||||
$bbcodes = array();
|
||||
|
||||
// Collect the name of the BBCodes whose bit is set in the style's bbcode_bitfield
|
||||
$template_bitfield = new \bitfield($style['bbcode_bitfield']);
|
||||
foreach ($bbcode_ids as $bbcode_name => $bit)
|
||||
{
|
||||
if ($template_bitfield->get($bit))
|
||||
{
|
||||
$bbcodes[] = $bbcode_name;
|
||||
}
|
||||
}
|
||||
|
||||
$filename = $this->resolve_style_filename($styles, $style);
|
||||
if ($filename === false)
|
||||
{
|
||||
// Ignore this style, it will use the default templates
|
||||
continue;
|
||||
}
|
||||
|
||||
$templates[$style_id] = array(
|
||||
'bbcodes' => $bbcodes,
|
||||
'template' => file_get_contents($filename),
|
||||
);
|
||||
}
|
||||
|
||||
return $templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve inheritance for given style and return the path to their bbcode.html file
|
||||
*
|
||||
* @param array $styles Associative array of [style_id => style] containing all styles
|
||||
* @param array $style Style for which we resolve
|
||||
* @return string|bool Path to this style's bbcode.html, or FALSE
|
||||
*/
|
||||
protected function resolve_style_filename(array $styles, array $style)
|
||||
{
|
||||
// Look for a bbcode.html in this style's dir
|
||||
$filename = $this->styles_path . $style['style_path'] . '/template/bbcode.html';
|
||||
if (file_exists($filename))
|
||||
{
|
||||
return $filename;
|
||||
}
|
||||
|
||||
// Resolve using this style's parent
|
||||
$parent_id = $style['style_parent_id'];
|
||||
if ($parent_id && !empty($styles[$parent_id]))
|
||||
{
|
||||
return $this->resolve_style_filename($styles, $styles[$parent_id]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of censored words
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_words()
|
||||
{
|
||||
$sql = 'SELECT word, replacement FROM ' . $this->words_table;
|
||||
$result = $this->db->sql_query($sql);
|
||||
$rows = $this->db->sql_fetchrowset($result);
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $rows;
|
||||
}
|
||||
}
|
121
phpBB/phpbb/textformatter/parser.php
Normal file
121
phpBB/phpbb/textformatter/parser.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\textformatter;
|
||||
|
||||
/**
|
||||
* text_formatter.parser service
|
||||
* @package phpBB3
|
||||
*/
|
||||
abstract class parser
|
||||
{
|
||||
/**
|
||||
* Parse given text
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
abstract public function parse($text);
|
||||
|
||||
/**
|
||||
* Disable a specific BBCode
|
||||
*
|
||||
* @param string $name BBCode name
|
||||
* @return null
|
||||
*/
|
||||
abstract public function disable_bbcode($name);
|
||||
|
||||
/**
|
||||
* Disable BBCodes in general
|
||||
*/
|
||||
abstract public function disable_bbcodes();
|
||||
|
||||
/**
|
||||
* Disable the censor
|
||||
*/
|
||||
abstract public function disable_censor();
|
||||
|
||||
/**
|
||||
* Disable magic URLs
|
||||
*/
|
||||
abstract public function disable_magic_url();
|
||||
|
||||
/**
|
||||
* Disable smilies
|
||||
*/
|
||||
abstract public function disable_smilies();
|
||||
|
||||
/**
|
||||
* Enable a specific BBCode
|
||||
*
|
||||
* @param string $name BBCode name
|
||||
* @return null
|
||||
*/
|
||||
abstract public function enable_bbcode($name);
|
||||
|
||||
/**
|
||||
* Enable BBCodes in general
|
||||
*/
|
||||
abstract public function enable_bbcodes();
|
||||
|
||||
/**
|
||||
* Enable the censor
|
||||
*/
|
||||
abstract public function enable_censor();
|
||||
|
||||
/**
|
||||
* Enable magic URLs
|
||||
*/
|
||||
abstract public function enable_magic_url();
|
||||
|
||||
/**
|
||||
* Enable smilies
|
||||
*/
|
||||
abstract public function enable_smilies();
|
||||
|
||||
/**
|
||||
* Get the list of errors that were generated during last parsing
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function get_errors();
|
||||
|
||||
/**
|
||||
* Set a variable to be used by the parser
|
||||
*
|
||||
* - max_font_size
|
||||
* - max_img_height
|
||||
* - max_img_width
|
||||
* - max_smilies
|
||||
* - max_urls
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
* @return null
|
||||
*/
|
||||
abstract public function set_var($name, $value);
|
||||
|
||||
/**
|
||||
* Set multiple variables to be used by the parser
|
||||
*
|
||||
* @param array Associative array of [name => value]
|
||||
* @return null
|
||||
*/
|
||||
public function set_vars(array $vars)
|
||||
{
|
||||
foreach ($vars as $name => $value)
|
||||
{
|
||||
$this->set_var($name, $value);
|
||||
}
|
||||
}
|
||||
}
|
136
phpBB/phpbb/textformatter/renderer.php
Normal file
136
phpBB/phpbb/textformatter/renderer.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\textformatter;
|
||||
|
||||
/**
|
||||
* text_formatter.renderer service
|
||||
* @package phpBB3
|
||||
*/
|
||||
abstract class renderer
|
||||
{
|
||||
/**
|
||||
* Render given text
|
||||
*
|
||||
* @param string $text Text, as parsed by the text_formatter.parser service
|
||||
* @return string
|
||||
*/
|
||||
abstract public function render($text);
|
||||
|
||||
/**
|
||||
* Automatically set the smilies path based on config
|
||||
*
|
||||
* Called by the service container
|
||||
*
|
||||
* @param phpbb\config\config $config
|
||||
* @param phpbb\path_helper $path_helper
|
||||
* @return null
|
||||
*/
|
||||
public function configure_smilies_path(\phpbb\config\config $config, \phpbb\path_helper $path_helper)
|
||||
{
|
||||
/**
|
||||
* @see smiley_text()
|
||||
*/
|
||||
$root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $path_helper->get_web_root_path();
|
||||
|
||||
$this->set_smilies_path($root_path . $config['smilies_path']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure this renderer as per the user's settings
|
||||
*
|
||||
* Should set the locale as well as the viewcensor/viewflash/viewimg/viewsmilies options.
|
||||
* Called by the service container
|
||||
*
|
||||
* @param phpbb\user $user
|
||||
* @param phpbb\config\config $config
|
||||
* @param phpbb\auth\auth $auth
|
||||
* @return null
|
||||
*/
|
||||
public function configure_user(\phpbb\user $user, \phpbb\config\config $config, \phpbb\auth\auth $auth)
|
||||
{
|
||||
$censor = $user->optionget('viewcensors') || !$config['allow_nocensors'] || !$auth->acl_get('u_chgcensors');
|
||||
|
||||
$this->set_viewcensors($censor);
|
||||
$this->set_viewflash($user->optionget('viewflash'));
|
||||
$this->set_viewimg($user->optionget('viewimg'));
|
||||
$this->set_viewsmilies($user->optionget('viewsmilies'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the smilies' path
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
abstract public function set_smilies_path($path);
|
||||
|
||||
/**
|
||||
* Return the value of the "viewcensors" option
|
||||
*
|
||||
* @return bool Option's value
|
||||
*/
|
||||
abstract public function get_viewcensors();
|
||||
|
||||
/**
|
||||
* Return the value of the "viewflash" option
|
||||
*
|
||||
* @return bool Option's value
|
||||
*/
|
||||
abstract public function get_viewflash();
|
||||
|
||||
/**
|
||||
* Return the value of the "viewimg" option
|
||||
*
|
||||
* @return bool Option's value
|
||||
*/
|
||||
abstract public function get_viewimg();
|
||||
|
||||
/**
|
||||
* Return the value of the "viewsmilies" option
|
||||
*
|
||||
* @return bool Option's value
|
||||
*/
|
||||
abstract public function get_viewsmilies();
|
||||
|
||||
/**
|
||||
* Set the "viewcensors" option
|
||||
*
|
||||
* @param bool $value Option's value
|
||||
* @return null
|
||||
*/
|
||||
abstract public function set_viewcensors($value);
|
||||
|
||||
/**
|
||||
* Set the "viewflash" option
|
||||
*
|
||||
* @param bool $value Option's value
|
||||
* @return null
|
||||
*/
|
||||
abstract public function set_viewflash($value);
|
||||
|
||||
/**
|
||||
* Set the "viewimg" option
|
||||
*
|
||||
* @param bool $value Option's value
|
||||
* @return null
|
||||
*/
|
||||
abstract public function set_viewimg($value);
|
||||
|
||||
/**
|
||||
* Set the "viewsmilies" option
|
||||
*
|
||||
* @param bool $value Option's value
|
||||
* @return null
|
||||
*/
|
||||
abstract public function set_viewsmilies($value);
|
||||
}
|
493
phpBB/phpbb/textformatter/s9e/factory.php
Normal file
493
phpBB/phpbb/textformatter/s9e/factory.php
Normal file
@@ -0,0 +1,493 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\textformatter\s9e;
|
||||
|
||||
use s9e\TextFormatter\Configurator;
|
||||
use s9e\TextFormatter\Configurator\Items\AttributeFilters\Regexp as RegexpFilter;
|
||||
|
||||
/**
|
||||
* Creates s9e\TextFormatter objects
|
||||
* @package phpBB3
|
||||
*/
|
||||
class factory implements \phpbb\textformatter\cache
|
||||
{
|
||||
/**
|
||||
* @var phpbb_cache_driver_interface $cache
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* @var string Path to the cache dir
|
||||
*/
|
||||
protected $cache_dir;
|
||||
|
||||
/**
|
||||
* @var string Cache key used for the parser
|
||||
*/
|
||||
protected $cache_key_parser;
|
||||
|
||||
/**
|
||||
* @var string Cache key used for the renderer
|
||||
*/
|
||||
protected $cache_key_renderer;
|
||||
|
||||
/**
|
||||
* @var array Custom tokens used in bbcode.html and their corresponding token from the definition
|
||||
*/
|
||||
protected $custom_tokens = array(
|
||||
'email' => array('{DESCRIPTION}' => '{TEXT}'),
|
||||
'flash' => array('{WIDTH}' => '{NUMBER1}', '{HEIGHT}' => '{NUMBER2}'),
|
||||
'img' => array('{URL}' => '{IMAGEURL}'),
|
||||
'list' => array('{LIST_TYPE}' => '{HASHMAP}'),
|
||||
'quote' => array('{USERNAME}' => '{TEXT1}'),
|
||||
'size' => array('{SIZE}' => '{FONTSIZE}'),
|
||||
'url' => array('{DESCRIPTION}' => '{TEXT}'),
|
||||
);
|
||||
|
||||
/**
|
||||
* @var \phpbb\textformatter\data_access
|
||||
*/
|
||||
protected $dal;
|
||||
|
||||
/**
|
||||
* @var array Default BBCode definitions
|
||||
*/
|
||||
protected $default_definitions = array(
|
||||
'attachment' => '[ATTACHMENT index={NUMBER} filename={TEXT;useContent}]',
|
||||
'b' => '[B]{TEXT}[/B]',
|
||||
'code' => '[CODE]{TEXT}[/CODE]',
|
||||
'color' => '[COLOR={COLOR}]{TEXT}[/COLOR]',
|
||||
'email' => '[EMAIL={EMAIL;useContent}]{TEXT}[/EMAIL]',
|
||||
'flash' => '[FLASH={NUMBER1},{NUMBER2} width={NUMBER1;postFilter=#flashwidth} height={NUMBER2;postFilter=#flashheight} url={URL;useContent} /]',
|
||||
'i' => '[I]{TEXT}[/I]',
|
||||
'img' => '[IMG src={IMAGEURL;useContent}]',
|
||||
'list' => '[LIST type={HASHMAP=1:decimal,a:lower-alpha,A:upper-alpha,i:lower-roman,I:upper-roman;optional;postFilter=#simpletext}]{TEXT}[/LIST]',
|
||||
'li' => '[* $tagName=LI]{TEXT}[/*]',
|
||||
'quote' => '[QUOTE author={TEXT1;optional}]{TEXT2}[/QUOTE]',
|
||||
'size' => '[SIZE={FONTSIZE}]{TEXT}[/SIZE]',
|
||||
'u' => '[U]{TEXT}[/U]',
|
||||
'url' => '[URL={URL;useContent}]{TEXT}[/URL]',
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array Default templates, taken from bbcode::bbcode_tpl()
|
||||
*/
|
||||
protected $default_templates = array(
|
||||
'b' => '<span style="font-weight: bold"><xsl:apply-templates/></span>',
|
||||
'i' => '<span style="font-style: italic"><xsl:apply-templates/></span>',
|
||||
'u' => '<span style="text-decoration: underline"><xsl:apply-templates/></span>',
|
||||
'img' => '<img src="{IMAGEURL}" alt="{L_IMAGE}"/>',
|
||||
'size' => '<span style="font-size: {FONTSIZE}%; line-height: normal"><xsl:apply-templates/></span>',
|
||||
'color' => '<span style="color: {COLOR}"><xsl:apply-templates/></span>',
|
||||
'email' => '<a href="mailto:{EMAIL}"><xsl:apply-templates/></a>',
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param phpbb\textformatter\data_access $dal
|
||||
* @param phpbb\cache\driver\driver_interface $cache
|
||||
* @param string $cache_dir Path to the cache dir
|
||||
* @param string $cache_key_parser Cache key used for the parser
|
||||
* @param string $cache_key_renderer Cache key used for the renderer
|
||||
* @return null
|
||||
*/
|
||||
public function __construct(\phpbb\textformatter\data_access $dal, \phpbb\cache\driver\driver_interface $cache, $cache_dir, $cache_key_parser, $cache_key_renderer)
|
||||
{
|
||||
$this->cache = $cache;
|
||||
$this->cache_dir = $cache_dir;
|
||||
$this->cache_key_parser = $cache_key_parser;
|
||||
$this->cache_key_renderer = $cache_key_renderer;
|
||||
|
||||
$this->dal = $dal;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function invalidate()
|
||||
{
|
||||
$this->regenerate();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Will remove old renderers from the cache dir but won't touch the current renderer
|
||||
*/
|
||||
public function tidy()
|
||||
{
|
||||
// Get the name of current renderer
|
||||
$renderer_data = $this->cache->get($this->cache_key_renderer);
|
||||
$renderer_file = ($renderer_data) ? $renderer_data['class'] . '.php' : null;
|
||||
|
||||
foreach (glob($this->cache_dir . 's9e_*') as $filename)
|
||||
{
|
||||
// Only remove the file if it's not the current renderer
|
||||
if (!$renderer_file || substr($filename, -strlen($renderer_file)) !== $renderer_file)
|
||||
{
|
||||
unlink($filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate and return a new configured instance of s9e\TextFormatter\Configurator
|
||||
*
|
||||
* @return s9e\TextFormatter\Configurator
|
||||
*/
|
||||
public function get_configurator()
|
||||
{
|
||||
// Create a new Configurator
|
||||
$configurator = new Configurator;
|
||||
|
||||
// Convert newlines to br elements by default
|
||||
$configurator->rootRules->enableAutoLineBreaks();
|
||||
|
||||
// Set the rendering engine and configure it to save to the cache dir
|
||||
$configurator->rendering->engine = 'PHP';
|
||||
$configurator->rendering->engine->cacheDir = $this->cache_dir;
|
||||
$configurator->rendering->engine->defaultClassPrefix = 's9e_renderer_';
|
||||
$configurator->rendering->engine->enableQuickRenderer = true;
|
||||
|
||||
// Create custom filters for BBCode tokens that are supported in phpBB but not in
|
||||
// s9e\TextFormatter
|
||||
$filter = new RegexpFilter('#^' . get_preg_expression('relative_url') . '$#D');
|
||||
$configurator->attributeFilters->add('#local_url', $filter);
|
||||
$configurator->attributeFilters->add('#relative_url', $filter);
|
||||
|
||||
$regexp = (phpbb_pcre_utf8_support())
|
||||
? '!^([\p{L}\p{N}\-+,_. ]+)$!uD'
|
||||
: '!^([a-zA-Z0-9\-+,_. ]+)$!uD';
|
||||
$configurator->attributeFilters->add('#inttext', new RegexpFilter($regexp));
|
||||
|
||||
// Create custom filters for Flash restrictions, which use the same values as the image
|
||||
// restrictions but have their own error message
|
||||
$configurator->attributeFilters
|
||||
->add('#flashheight', __NAMESPACE__ . '\\parser::filter_flash_height')
|
||||
->addParameterByName('max_img_height')
|
||||
->addParameterByName('logger');
|
||||
|
||||
$configurator->attributeFilters
|
||||
->add('#flashwidth', __NAMESPACE__ . '\\parser::filter_flash_width')
|
||||
->addParameterByName('max_img_width')
|
||||
->addParameterByName('logger');
|
||||
|
||||
// Create a custom filter for phpBB's per-mode font size limits
|
||||
$configurator->attributeFilters
|
||||
->add('#fontsize', __NAMESPACE__ . '\\parser::filter_font_size')
|
||||
->addParameterByName('max_font_size')
|
||||
->addParameterByName('logger')
|
||||
->markAsSafeInCSS();
|
||||
|
||||
// Create a custom filter for image URLs
|
||||
$configurator->attributeFilters
|
||||
->add('#imageurl', __NAMESPACE__ . '\\parser::filter_img_url')
|
||||
->addParameterByName('urlConfig')
|
||||
->addParameterByName('logger')
|
||||
->addParameterByName('max_img_height')
|
||||
->addParameterByName('max_img_width')
|
||||
->markAsSafeAsURL();
|
||||
|
||||
// Add default BBCodes
|
||||
foreach ($this->get_default_bbcodes($configurator) as $bbcode)
|
||||
{
|
||||
$configurator->BBCodes->addCustom($bbcode['usage'], $bbcode['template']);
|
||||
}
|
||||
|
||||
// Modify the template to disable images/flash depending on user's settings
|
||||
foreach (array('FLASH', 'IMG') as $name)
|
||||
{
|
||||
$tag = $configurator->tags[$name];
|
||||
$tag->template = '<xsl:choose><xsl:when test="$S_VIEW' . $name . '">' . $tag->template . '</xsl:when><xsl:otherwise><xsl:apply-templates/></xsl:otherwise></xsl:choose>';
|
||||
}
|
||||
|
||||
// Load custom BBCodes
|
||||
foreach ($this->dal->get_bbcodes() as $row)
|
||||
{
|
||||
// Insert the board's URL before {LOCAL_URL} tokens
|
||||
$tpl = preg_replace_callback(
|
||||
'#\\{LOCAL_URL\\d*\\}#',
|
||||
function ($m)
|
||||
{
|
||||
return generate_board_url() . '/' . $m[0];
|
||||
},
|
||||
$row['bbcode_tpl']
|
||||
);
|
||||
|
||||
try
|
||||
{
|
||||
$configurator->BBCodes->addCustom($row['bbcode_match'], $tpl);
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
/**
|
||||
* @todo log an error?
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
// Load smilies
|
||||
foreach ($this->dal->get_smilies() as $row)
|
||||
{
|
||||
$configurator->Emoticons->add(
|
||||
$row['code'],
|
||||
'<img class="smilies" src="{$T_SMILIES_PATH}/' . htmlspecialchars($row['smiley_url']) . '" alt="{.}" title="' . htmlspecialchars($row['emotion']) . '"/>'
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($configurator->Emoticons))
|
||||
{
|
||||
// Force emoticons to be rendered as text if $S_VIEWSMILIES is not set
|
||||
$configurator->Emoticons->notIfCondition = 'not($S_VIEWSMILIES)';
|
||||
|
||||
// Only parse emoticons at the beginning of the text or if they're preceded by any
|
||||
// one of: a new line, a space, a dot, or a right square bracket
|
||||
$configurator->Emoticons->notAfter = '[^\\n .\\]]';
|
||||
}
|
||||
|
||||
// Load the censored words
|
||||
foreach ($this->dal->get_words() as $row)
|
||||
{
|
||||
$configurator->Censor->add($row['word'], $row['replacement']);
|
||||
}
|
||||
|
||||
if (isset($configurator->Censor))
|
||||
{
|
||||
// Replace the template with a template that applies only when $S_VIEWCENSORS is set
|
||||
$tag = $configurator->Censor->getTag();
|
||||
$tag->template =
|
||||
'<xsl:choose>
|
||||
<xsl:when test="not($S_VIEWCENSORS)">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:when>
|
||||
<xsl:when test="@with">
|
||||
<xsl:value-of select="@with"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>****</xsl:otherwise>
|
||||
</xsl:choose>';
|
||||
}
|
||||
|
||||
// Load the magic links plugins. We do that after BBCodes so that they use the same tags
|
||||
$configurator->plugins->load('Autoemail');
|
||||
$configurator->plugins->load('Autolink');
|
||||
|
||||
// Register some vars with a default value. Those should be set at runtime by whatever calls
|
||||
// the parser
|
||||
$configurator->registeredVars['max_font_size'] = 0;
|
||||
$configurator->registeredVars['max_img_height'] = 0;
|
||||
$configurator->registeredVars['max_img_width'] = 0;
|
||||
|
||||
return $configurator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Regenerate and cache a new parser and renderer
|
||||
*
|
||||
* @return array Array with two elements: an instance of the parser, an instance of the renderer
|
||||
*/
|
||||
public function regenerate()
|
||||
{
|
||||
$configurator = $this->get_configurator();
|
||||
|
||||
// Create $parser and $renderer
|
||||
extract($configurator->finalize());
|
||||
|
||||
// Cache the parser as-is
|
||||
$this->cache->put($this->cache_key_parser, $parser);
|
||||
|
||||
// We need to cache the name of the renderer's generated class so that we can load the class
|
||||
// before the renderer is unserialized. That's why we save them together, with the renderer
|
||||
// in serialized form
|
||||
$renderer_data = array(
|
||||
'class' => get_class($renderer),
|
||||
'renderer' => serialize($renderer)
|
||||
);
|
||||
$this->cache->put($this->cache_key_renderer, $renderer_data);
|
||||
|
||||
return array($parser, $renderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default BBCodes configuration
|
||||
*
|
||||
* @return array 2D array. Each element has a 'usage' key, a 'template' key, and an optional 'options' key
|
||||
*/
|
||||
protected function get_default_bbcodes($configurator)
|
||||
{
|
||||
// For each BBCode, build an associative array matching style_ids to their template
|
||||
$templates = array();
|
||||
foreach ($this->dal->get_styles_templates() as $style_id => $data)
|
||||
{
|
||||
foreach ($this->extract_templates($data['template']) as $bbcode_name => $template)
|
||||
{
|
||||
$templates[$bbcode_name][$style_id] = $template;
|
||||
}
|
||||
|
||||
// Add default templates wherever missing, or for BBCodes that were not specified in
|
||||
// this template's bitfield. For instance, prosilver has a custom template for b but its
|
||||
// bitfield does not enable it so the default template is used instead
|
||||
foreach ($this->default_templates as $bbcode_name => $template)
|
||||
{
|
||||
if (!isset($templates[$bbcode_name][$style_id]) || !in_array($bbcode_name, $data['bbcodes'], true))
|
||||
{
|
||||
$templates[$bbcode_name][$style_id] = $template;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replace custom tokens and normalize templates
|
||||
foreach ($templates as $bbcode_name => &$style_templates)
|
||||
{
|
||||
foreach ($style_templates as &$template)
|
||||
{
|
||||
if (isset($this->custom_tokens[$bbcode_name]))
|
||||
{
|
||||
$template = strtr($template, $this->custom_tokens[$bbcode_name]);
|
||||
}
|
||||
|
||||
$template = $configurator->templateNormalizer->normalizeTemplate($template);
|
||||
}
|
||||
unset($template);
|
||||
}
|
||||
unset($style_templates);
|
||||
|
||||
$bbcodes = array();
|
||||
foreach ($this->default_definitions as $bbcode_name => $usage)
|
||||
{
|
||||
$bbcodes[$bbcode_name] = array(
|
||||
'usage' => $usage,
|
||||
'template' => $this->merge_templates($templates[$bbcode_name]),
|
||||
);
|
||||
}
|
||||
|
||||
return $bbcodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract and recompose individual BBCode templates from a style's template file
|
||||
*
|
||||
* @param string $template Style template (bbcode.html)
|
||||
* @return array Associative array matching BBCode names to their template
|
||||
*/
|
||||
protected function extract_templates($template)
|
||||
{
|
||||
// Capture the template fragments
|
||||
preg_match_all('#<!-- BEGIN (.*?) -->(.*?)<!-- END .*? -->#s', $template, $matches, PREG_SET_ORDER);
|
||||
|
||||
$fragments = array();
|
||||
foreach ($matches as $match)
|
||||
{
|
||||
// Normalize the whitespace
|
||||
$fragment = preg_replace('#>\\n\\t*<#', '><', trim($match[2]));
|
||||
|
||||
$fragments[$match[1]] = $fragment;
|
||||
}
|
||||
|
||||
// Automatically recompose templates split between *_open and *_close
|
||||
foreach ($fragments as $fragment_name => $fragment)
|
||||
{
|
||||
if (preg_match('#^(\\w+)_close$#', $fragment_name, $match))
|
||||
{
|
||||
$bbcode_name = $match[1];
|
||||
|
||||
if (isset($fragments[$bbcode_name . '_open']))
|
||||
{
|
||||
$templates[$bbcode_name] = $fragments[$bbcode_name . '_open'] . '<xsl:apply-templates/>' . $fragment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Manually recompose and overwrite irregular templates
|
||||
$templates['list'] =
|
||||
'<xsl:choose>
|
||||
<xsl:when test="not(@type)">
|
||||
' . $fragments['ulist_open_default'] . '<xsl:apply-templates/>' . $fragments['ulist_close'] . '
|
||||
</xsl:when>
|
||||
<xsl:when test="contains(\'upperlowerdecim\',substring(@type,1,5))">
|
||||
' . $fragments['olist_open'] . '<xsl:apply-templates/>' . $fragments['olist_close'] . '
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
' . $fragments['ulist_open'] . '<xsl:apply-templates/>' . $fragments['ulist_close'] . '
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>';
|
||||
|
||||
$templates['li'] = $fragments['listitem'] . '<xsl:apply-templates/>' . $fragments['listitem_close'];
|
||||
|
||||
$templates['quote'] =
|
||||
'<xsl:choose>
|
||||
<xsl:when test="@author">
|
||||
' . $fragments['quote_username_open'] . '<xsl:apply-templates/>' . $fragments['quote_close'] . '
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
' . $fragments['quote_open'] . '<xsl:apply-templates/>' . $fragments['quote_close'] . '
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>';
|
||||
|
||||
// The [attachment] BBCode uses the inline_attachment template to output a comment that
|
||||
// is post-processed by parse_attachments()
|
||||
$templates['attachment'] = $fragments['inline_attachment_open'] . '<xsl:comment> ia<xsl:value-of select="@index"/> </xsl:comment><xsl:value-of select="@filename"/><xsl:comment> ia<xsl:value-of select="@index"/> </xsl:comment>' . $fragments['inline_attachment_close'];
|
||||
|
||||
// Finally save fragments whose names look like the name of a BBCode, e.g. "flash"
|
||||
foreach ($fragments as $fragment_name => $fragment)
|
||||
{
|
||||
if (preg_match('#^\\w+$#', $fragment_name))
|
||||
{
|
||||
$templates[$fragment_name] = $fragment;
|
||||
}
|
||||
}
|
||||
|
||||
return $templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the templates from any number of styles into one BBCode template
|
||||
*
|
||||
* @param array $style_templates Associative array matching style_ids to their template
|
||||
* @return string
|
||||
*/
|
||||
protected function merge_templates(array $style_templates)
|
||||
{
|
||||
// Group identical templates together
|
||||
$grouped_templates = array();
|
||||
foreach ($style_templates as $style_id => $style_template)
|
||||
{
|
||||
$grouped_templates[$style_template][] = $style_id;
|
||||
}
|
||||
|
||||
if (count($grouped_templates) === 1)
|
||||
{
|
||||
return $style_template;
|
||||
}
|
||||
|
||||
// Sort templates by frequency descending
|
||||
$templates_cnt = array_map('sizeof', $grouped_templates);
|
||||
array_multisort($grouped_templates, $templates_cnt);
|
||||
|
||||
// Remove the most frequent template from the list; It becomes the default
|
||||
reset($grouped_templates);
|
||||
$default_template = key($grouped_templates);
|
||||
unset($grouped_templates[$default_template]);
|
||||
|
||||
// Build an xsl:choose switch
|
||||
$template = '<xsl:choose>';
|
||||
foreach ($grouped_templates as $style_template => $style_ids)
|
||||
{
|
||||
$template .= '<xsl:when test="$STYLE_ID=' . implode(' or $STYLE_ID=', $style_ids) . '">' . $style_template . '</xsl:when>';
|
||||
}
|
||||
$template .= '<xsl:otherwise>' . $default_template . '</xsl:otherwise></xsl:choose>';
|
||||
|
||||
return $template;
|
||||
}
|
||||
}
|
335
phpBB/phpbb/textformatter/s9e/parser.php
Normal file
335
phpBB/phpbb/textformatter/s9e/parser.php
Normal file
@@ -0,0 +1,335 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\textformatter\s9e;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use s9e\TextFormatter\Parser\BuiltInFilters;
|
||||
use s9e\TextFormatter\Parser\Logger;
|
||||
|
||||
/**
|
||||
* s9e\TextFormatter\Parser adapter
|
||||
* @package phpBB3
|
||||
*/
|
||||
class parser extends \phpbb\textformatter\parser
|
||||
{
|
||||
/**
|
||||
* @var s9e\TextFormatter\Parser
|
||||
*/
|
||||
protected $parser;
|
||||
|
||||
/**
|
||||
* @var phpbb\user User object, used for translating errors
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param phpbb\cache\driver_interface $cache
|
||||
* @param string $key Cache key
|
||||
* @param phpbb\user $user
|
||||
* @param Symfony\Component\DependencyInjection\ContainerInterface $container
|
||||
* @return null
|
||||
*/
|
||||
public function __construct(\phpbb\cache\driver\driver_interface $cache, $key, \phpbb\user $user, ContainerInterface $container)
|
||||
{
|
||||
$this->user = $user;
|
||||
|
||||
$parser = $cache->get($key);
|
||||
if (!$parser)
|
||||
{
|
||||
list($parser) = $container->get('text_formatter.s9e.factory')->regenerate();
|
||||
}
|
||||
|
||||
$this->parser = $parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parse($text)
|
||||
{
|
||||
return $this->parser->parse($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function disable_bbcode($name)
|
||||
{
|
||||
$this->parser->disableTag(strtoupper($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function disable_bbcodes()
|
||||
{
|
||||
$this->parser->disablePlugin('BBCodes');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function disable_censor()
|
||||
{
|
||||
$this->parser->disablePlugin('Censor');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function disable_magic_url()
|
||||
{
|
||||
$this->parser->disablePlugin('Autoemail');
|
||||
$this->parser->disablePlugin('Autolink');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function disable_smilies()
|
||||
{
|
||||
$this->parser->disablePlugin('Emoticons');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function enable_bbcode($name)
|
||||
{
|
||||
$this->parser->enableTag(strtoupper($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function enable_bbcodes()
|
||||
{
|
||||
$this->parser->enablePlugin('BBCodes');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function enable_censor()
|
||||
{
|
||||
$this->parser->enablePlugin('Censor');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function enable_magic_url()
|
||||
{
|
||||
$this->parser->enablePlugin('Autoemail');
|
||||
$this->parser->enablePlugin('Autolink');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function enable_smilies()
|
||||
{
|
||||
$this->parser->enablePlugin('Emoticons');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* This will translate the log entries found in s9e\TextFormatter's logger into phpBB error
|
||||
* messages
|
||||
*/
|
||||
public function get_errors()
|
||||
{
|
||||
$errors = array();
|
||||
|
||||
foreach ($this->parser->getLogger()->get() as $entry)
|
||||
{
|
||||
list($type, $msg, $context) = $entry;
|
||||
|
||||
if ($msg === 'Tag limit exceeded')
|
||||
{
|
||||
if ($context['tagName'] === 'E')
|
||||
{
|
||||
$errors[] = $this->user->lang('TOO_MANY_SMILIES', $context['tagLimit']);
|
||||
}
|
||||
else if ($context['tagName'] === 'URL')
|
||||
{
|
||||
$errors[] = $this->user->lang('TOO_MANY_URLS', $context['tagLimit']);
|
||||
}
|
||||
}
|
||||
else if ($msg === 'MAX_FONT_SIZE_EXCEEDED')
|
||||
{
|
||||
$errors[] = $this->user->lang($msg, $context['max_size']);
|
||||
}
|
||||
else if (preg_match('/^MAX_(?:FLASH|IMG)_(HEIGHT|WIDTH)_EXCEEDED$/D', $msg, $m))
|
||||
{
|
||||
$errors[] = $this->user->lang($msg, $context['max_' . strtolower($m[1])]);
|
||||
}
|
||||
else if ($msg === 'Tag is disabled')
|
||||
{
|
||||
$name = strtolower($context['tag']->getName());
|
||||
$errors[] = $this->user->lang('UNAUTHORISED_BBCODE', '[' . $name . ']');
|
||||
}
|
||||
else if ($msg === 'UNABLE_GET_IMAGE_SIZE')
|
||||
{
|
||||
$errors[] = $this->user->lang[$msg];
|
||||
}
|
||||
}
|
||||
|
||||
return array_unique($errors);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set_var($name, $value)
|
||||
{
|
||||
if ($name === 'max_smilies')
|
||||
{
|
||||
$this->parser->setTagLimit('E', $value ?: PHP_INT_MAX);
|
||||
}
|
||||
else if ($name === 'max_urls')
|
||||
{
|
||||
$this->parser->setTagLimit('URL', $value ?: PHP_INT_MAX);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parser->registeredVars[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter a flash object's height
|
||||
*
|
||||
* @see bbcode_firstpass::bbcode_flash()
|
||||
*
|
||||
* @param string $height
|
||||
* @param integer $max_height
|
||||
* @param s9e\TextFormatter\Parser\Logger $logger
|
||||
* @return mixed Original value if valid, FALSE otherwise
|
||||
*/
|
||||
static public function filter_flash_height($height, $max_height, Logger $logger)
|
||||
{
|
||||
if ($max_height && $height > $max_height)
|
||||
{
|
||||
$logger->err('MAX_FLASH_HEIGHT_EXCEEDED', array('max_height' => $max_height));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter a flash object's width
|
||||
*
|
||||
* @see bbcode_firstpass::bbcode_flash()
|
||||
*
|
||||
* @param string $width
|
||||
* @param integer $max_width
|
||||
* @param s9e\TextFormatter\Parser\Logger $logger
|
||||
* @return mixed Original value if valid, FALSE otherwise
|
||||
*/
|
||||
static public function filter_flash_width($width, $max_width, Logger $logger)
|
||||
{
|
||||
if ($max_width && $width > $max_width)
|
||||
{
|
||||
$logger->err('MAX_FLASH_WIDTH_EXCEEDED', array('max_width' => $max_width));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the value used in a [size] BBCode
|
||||
*
|
||||
* @see bbcode_firstpass::bbcode_size()
|
||||
*
|
||||
* @param string $size Original size
|
||||
* @param integer $max_size Maximum allowed size
|
||||
* @param s9e\TextFormatter\Parser\Logger $logger
|
||||
* @return mixed Original value if valid, FALSE otherwise
|
||||
*/
|
||||
static public function filter_font_size($size, $max_size, Logger $logger)
|
||||
{
|
||||
if ($max_size && $size > $max_size)
|
||||
{
|
||||
$logger->err('MAX_FONT_SIZE_EXCEEDED', array('max_size' => $max_size));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($size < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return $size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter an image's URL to enforce restrictions on its dimensions
|
||||
*
|
||||
* @see bbcode_firstpass::bbcode_img()
|
||||
*
|
||||
* @param string $url Original URL
|
||||
* @param array $url_config Config used by the URL filter
|
||||
* @param s9e\TextFormatter\Parser\Logger $logger
|
||||
* @param integer $max_height Maximum height allowed
|
||||
* @param integer $max_width Maximum width allowed
|
||||
* @return string|bool Original value if valid, FALSE otherwise
|
||||
*/
|
||||
static public function filter_img_url($url, array $url_config, Logger $logger, $max_height, $max_width)
|
||||
{
|
||||
// Validate the URL
|
||||
$url = BuiltInFilters::filterUrl($url, $url_config, $logger);
|
||||
|
||||
if ($url === false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($max_height || $max_width)
|
||||
{
|
||||
$stats = @getimagesize($url);
|
||||
|
||||
if ($stats === false)
|
||||
{
|
||||
$logger->err('UNABLE_GET_IMAGE_SIZE');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($max_height && $max_height < $stats[1])
|
||||
{
|
||||
$logger->err('MAX_IMG_HEIGHT_EXCEEDED', array('max_height' => $max_height));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($max_width && $max_width < $stats[0])
|
||||
{
|
||||
$logger->err('MAX_IMG_WIDTH_EXCEEDED', array('max_width' => $max_width));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
}
|
228
phpBB/phpbb/textformatter/s9e/renderer.php
Normal file
228
phpBB/phpbb/textformatter/s9e/renderer.php
Normal file
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\textformatter\s9e;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* s9e\TextFormatter\Renderer adapter
|
||||
* @package phpBB3
|
||||
*/
|
||||
class renderer extends \phpbb\textformatter\renderer
|
||||
{
|
||||
/**
|
||||
* @var s9e\TextFormatter\Renderer
|
||||
*/
|
||||
protected $renderer;
|
||||
|
||||
/**
|
||||
* @var bool Status of the viewcensors option
|
||||
*/
|
||||
protected $viewcensors = false;
|
||||
|
||||
/**
|
||||
* @var bool Status of the viewflash option
|
||||
*/
|
||||
protected $viewflash = false;
|
||||
|
||||
/**
|
||||
* @var bool Status of the viewimg option
|
||||
*/
|
||||
protected $viewimg = false;
|
||||
|
||||
/**
|
||||
* @var bool Status of the viewsmilies option
|
||||
*/
|
||||
protected $viewsmilies = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param phpbb\cache\driver\driver_interface $cache
|
||||
* @param string $cache_dir Path to the cache dir
|
||||
* @param string $key Cache key
|
||||
* @param Symfony\Component\DependencyInjection\ContainerInterface $container
|
||||
* @return null
|
||||
*/
|
||||
public function __construct(\phpbb\cache\driver\driver_interface $cache, $cache_dir, $key, ContainerInterface $container)
|
||||
{
|
||||
$renderer_data = $cache->get($key);
|
||||
|
||||
if ($renderer_data)
|
||||
{
|
||||
$class = $renderer_data['class'];
|
||||
|
||||
if (!class_exists($class, false))
|
||||
{
|
||||
// Try to load the renderer class from its cache file
|
||||
$cache_file = $cache_dir . $class . '.php';
|
||||
|
||||
if (file_exists($cache_file))
|
||||
{
|
||||
include($cache_file);
|
||||
}
|
||||
}
|
||||
|
||||
if (class_exists($class, false))
|
||||
{
|
||||
$renderer = unserialize($renderer_data['renderer']);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($renderer))
|
||||
{
|
||||
list(, $renderer) = $container->get('text_formatter.s9e.factory')->regenerate();
|
||||
}
|
||||
|
||||
$this->renderer = $renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function configure_user(\phpbb\user $user, \phpbb\config\config $config, \phpbb\auth\auth $auth)
|
||||
{
|
||||
parent::configure_user($user, $config, $auth);
|
||||
|
||||
// Set the stylesheet parameters
|
||||
foreach (array_keys($this->renderer->getParameters()) as $param_name)
|
||||
{
|
||||
if (substr($param_name, 0, 2) === 'L_')
|
||||
{
|
||||
// L_FOO is set to $user->lang('FOO')
|
||||
$this->renderer->setParameter($param_name, $user->lang(substr($param_name, 2)));
|
||||
}
|
||||
}
|
||||
|
||||
// Set the style id
|
||||
$this->renderer->setParameter('STYLE_ID', $user->style['style_id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get_viewcensors()
|
||||
{
|
||||
return $this->viewcensors;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get_viewflash()
|
||||
{
|
||||
return $this->viewflash;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get_viewimg()
|
||||
{
|
||||
return $this->viewimg;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get_viewsmilies()
|
||||
{
|
||||
return $this->viewsmilies;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function render($text)
|
||||
{
|
||||
$html = $this->renderer->render($text);
|
||||
|
||||
/**
|
||||
* @see bbcode::bbcode_second_pass_code()
|
||||
*/
|
||||
$html = preg_replace_callback(
|
||||
'#(<code>)(.*?)(</code>)#is',
|
||||
function ($captures)
|
||||
{
|
||||
$code = $captures[2];
|
||||
|
||||
$code = str_replace("\t", ' ', $code);
|
||||
$code = str_replace(' ', ' ', $code);
|
||||
$code = str_replace(' ', ' ', $code);
|
||||
$code = str_replace("\n ", "\n ", $code);
|
||||
|
||||
// keep space at the beginning
|
||||
if (!empty($code) && $code[0] == ' ')
|
||||
{
|
||||
$code = ' ' . substr($code, 1);
|
||||
}
|
||||
|
||||
// remove newline at the beginning
|
||||
if (!empty($code) && $code[0] == "\n")
|
||||
{
|
||||
$code = substr($code, 1);
|
||||
}
|
||||
|
||||
return $captures[1] . $code . $captures[3];
|
||||
},
|
||||
$html
|
||||
);
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set_smilies_path($path)
|
||||
{
|
||||
$this->renderer->setParameter('T_SMILIES_PATH', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set_viewcensors($value)
|
||||
{
|
||||
$this->viewcensors = $value;
|
||||
$this->renderer->setParameter('S_VIEWCENSORS', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set_viewflash($value)
|
||||
{
|
||||
$this->viewflash = $value;
|
||||
$this->renderer->setParameter('S_VIEWFLASH', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set_viewimg($value)
|
||||
{
|
||||
$this->viewimg = $value;
|
||||
$this->renderer->setParameter('S_VIEWIMG', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set_viewsmilies($value)
|
||||
{
|
||||
$this->viewsmilies = $value;
|
||||
$this->renderer->setParameter('S_VIEWSMILIES', $value);
|
||||
}
|
||||
}
|
67
phpBB/phpbb/textformatter/s9e/utils.php
Normal file
67
phpBB/phpbb/textformatter/s9e/utils.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\textformatter\s9e;
|
||||
|
||||
/**
|
||||
* Text manipulation utilities
|
||||
* @package phpBB3
|
||||
*/
|
||||
class utils extends \phpbb\textformatter\utils
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clean_formatting($text)
|
||||
{
|
||||
// Insert a space before <s> and <e> then remove formatting
|
||||
$text = preg_replace('#<[es]>#', ' $0', $text);
|
||||
|
||||
return \s9e\TextFormatter\Unparser::removeFormatting($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function remove_bbcode($text, $bbcode_name, $depth = 0)
|
||||
{
|
||||
$dom = new \DOMDocument;
|
||||
$dom->loadXML($text);
|
||||
|
||||
$xpath = new \DOMXPath($dom);
|
||||
$nodes = $xpath->query(str_repeat('//' . strtoupper($bbcode_name), 1 + $depth));
|
||||
|
||||
foreach ($nodes as $node)
|
||||
{
|
||||
$node->parentNode->removeChild($node);
|
||||
}
|
||||
|
||||
return $dom->saveXML($dom->documentElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function remove_formatting($text)
|
||||
{
|
||||
return \s9e\TextFormatter\Unparser::removeFormatting($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function unparse($text)
|
||||
{
|
||||
return \s9e\TextFormatter\Unparser::unparse($text);
|
||||
}
|
||||
}
|
62
phpBB/phpbb/textformatter/utils.php
Normal file
62
phpBB/phpbb/textformatter/utils.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\textformatter;
|
||||
|
||||
/**
|
||||
* text_formatter.utils service
|
||||
*
|
||||
* Used to manipulate a parsed text
|
||||
*
|
||||
* @package phpBB3
|
||||
*/
|
||||
abstract class utils
|
||||
{
|
||||
/**
|
||||
* Replace BBCodes and other formatting elements with whitespace
|
||||
*
|
||||
* NOTE: preserves smilies as text
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
abstract public function clean_formatting($text);
|
||||
|
||||
/**
|
||||
* Remove given BBCode at given nesting depth
|
||||
*
|
||||
* @param string $text Parsed text
|
||||
* @param string $bbcode_name BBCode's name
|
||||
* @param integer $depth Minimum nesting depth (number of parents of the same name)
|
||||
* @return string
|
||||
*/
|
||||
abstract public function remove_bbcode($text, $bbcode_name, $depth = 0);
|
||||
|
||||
/**
|
||||
* Remove BBCodes and other formatting from a parsed text
|
||||
*
|
||||
* NOTE: preserves smilies as text
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
abstract public function remove_formatting($text);
|
||||
|
||||
/**
|
||||
* Return a parsed text to its original form
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
abstract public function unparse($text);
|
||||
}
|
Reference in New Issue
Block a user