From ffa83320d297d0f2608f81b0d7d858e343b3dd3c Mon Sep 17 00:00:00 2001 From: flashwave Date: Wed, 25 Nov 2015 21:18:52 +0100 Subject: [PATCH] r20151125 Signed-off-by: Flashwave --- _sakura/components/BBcode/BBcode.php | 52 ++++++ _sakura/components/BBcode/Parse.php | 140 +++++++++++++++ _sakura/components/BBcode/Store.php | 250 +++++++++++++++++++++++++++ _sakura/components/Forum/Post.php | 1 + _sakura/components/User.php | 2 +- _sakura/sakura.php | 5 +- 6 files changed, 448 insertions(+), 2 deletions(-) create mode 100644 _sakura/components/BBcode/BBcode.php create mode 100644 _sakura/components/BBcode/Parse.php create mode 100644 _sakura/components/BBcode/Store.php diff --git a/_sakura/components/BBcode/BBcode.php b/_sakura/components/BBcode/BBcode.php new file mode 100644 index 0000000..a6d0add --- /dev/null +++ b/_sakura/components/BBcode/BBcode.php @@ -0,0 +1,52 @@ +setText($text); + $this->seed = $seed; + } + + // Set text + public function setText($text) + { + $this->text = $text; + } + + // Convert to storage format + public function toStore() + { + // Create new Store + $store = new Store($this->text, $this->seed); + + // Parse + $store = $store->generate(); + + // And return + return $store; + } + + // Convert to storage format + public function toHTML() + { + // Create new Parse + $parse = new Parse($this->text, $this->seed); + + // Parse + $parse = $parse->parse(); + + // And return + return $parse; + } +} diff --git a/_sakura/components/BBcode/Parse.php b/_sakura/components/BBcode/Parse.php new file mode 100644 index 0000000..73c8d31 --- /dev/null +++ b/_sakura/components/BBcode/Parse.php @@ -0,0 +1,140 @@ + 'strong', + 'i' => 'em', + 'u' => 'u', + 's' => 'del', + 'h' => 'h2', + ]; + + // Advanced bbcodes + private $advanced = [ + 'spoiler' => '|', + ]; + + public function __construct($text = "", $seed = '9001') + { + $this->setText($text); + $this->seed = $seed; + } + + public function setText($text) + { + $this->text = $text; + } + + public function parseImage($text) + { + return preg_replace_callback( + "#\[img:{$this->seed}\](?[^[]+)\[/img:{$this->seed}\]#", + function ($i) { + return "\"{$i['url']}\""; + }, + $text + ); + } + + public function parseList($text) + { + $text = preg_replace("#\[list=\d+:{$this->seed}\]#", '
    ', $text); + $text = preg_replace("#\[list(=.?)?:{$this->seed}\]#", "
      ", $text); + $text = preg_replace("#\[/\*(:m)?:{$this->seed}\]\n?#", '', $text); + $text = str_replace("[*:{$this->seed}]", '
    1. ', $text); + $text = str_replace("[/list:o:{$this->seed}]", '
    ', $text); + $text = str_replace("[/list:u:{$this->seed}]", '
', $text); + + return $text; + } + + public function parseCode($text) + { + return preg_replace_callback( + "#[\r|\n]*\[code:{$this->seed}\][\r|\n]*(.*?)[\r|\n]*\[/code:{$this->seed}\][\r|\n]*#s", + function ($c) { + return '
' . str_replace('
', '', $c[1]) . '
'; + }, + $text + ); + } + + public function parseQuote($text) + { + $text = preg_replace("#\[quote="([^:]+)":{$this->seed}\]#", '

\\1 wrote:

', $text); + $text = str_replace("[quote:{$this->seed}]", '
', $text); + $text = str_replace("[/quote:{$this->seed}]", '
', $text); + + return $text; + } + + public function parseSimple($text) + { + // Parse all simple tags + foreach ($this->simple as $code => $tag) { + $text = str_replace("[{$code}:{$this->seed}]", "<{$tag}>", $text); + $text = str_replace("[/{$code}:{$this->seed}]", "", $text); + } + return $text; + } + + public function parseAdvanced($text) + { + // Parse all advanced tags + foreach ($this->advanced as $code => $tags) { + $tags = explode('|', $tags); + + $text = str_replace("[{$code}:{$this->seed}]", $tags[0], $text); + $text = str_replace("[/{$code}:{$this->seed}]", $tags[1], $text); + } + return $text; + } + + public function parseColour($text) + { + $text = preg_replace("#\[color=([^:]+):{$this->seed}\]#", "", $text); + $text = str_replace("[/color:{$this->seed}]", '', $text); + + return $text; + } + + public function parseUrl($text) + { + $text = preg_replace("#\[url:{$this->seed}\](.+?)\[/url:{$this->seed}\]#", "\\1", $text); + $text = preg_replace("#\[url=(.+?):{$this->seed}\]#", "", $text); + $text = str_replace("[/url:{$this->seed}]", '', $text); + + return $text; + } + + public function parse() + { + // Get text + $text = $this->text; + + $text = str_replace("\n", '
', $text); + + $text = $this->parseCode($text); + $text = $this->parseList($text); + $text = $this->parseQuote($text); + + $text = $this->parseAdvanced($text); + $text = $this->parseColour($text); + $text = $this->parseImage($text); + $text = $this->parseSimple($text); + $text = $this->parseUrl($text); + + return $text; + } +} diff --git a/_sakura/components/BBcode/Store.php b/_sakura/components/BBcode/Store.php new file mode 100644 index 0000000..e96777f --- /dev/null +++ b/_sakura/components/BBcode/Store.php @@ -0,0 +1,250 @@ + '[', + ']' => ']', + '.' => '.', + ':' => ':', + ]; + + // Spaces + protected $spaces = [ + "(^|\s)", + "((?:\.|\))?(?:$|\s|\n|\r))", + ]; + + // Simple bbcodes + protected $simple = [ + 'b', + 'i', + 'u', + 's', + 'h', + 'img', + 'spoiler', + ]; + + // Constructor + public function __construct($text = "", $seed = "") + { + $this->setText($text); + $this->seed = $seed; + } + + // Set text + public function setText($text) + { + $this->text = $text; + } + + // Colour tag + public function parseColour($text) + { + return preg_replace( + ",\[(color=(?:#[[:xdigit:]]{6}|[[:alpha:]]+))\](.+?)\[(/color)\],", + "[\\1:{$this->seed}]\\2[\\3:{$this->seed}]", + $text + ); + } + + // Align tag + public function parseAlign($text) + { + return preg_replace( + ",\[(align=(?:[[:alpha:]]+))\](.+?)\[(/align)\],", + "[\\1:{$this->seed}]\\2[\\3:{$this->seed}]", + $text + ); + } + + // Size tag + public function parseSize($text) + { + return preg_replace( + ",\[(size=(?:[[:digit:]]+))\](.+?)\[(/size)\],", + "[\\1:{$this->seed}]\\2[\\3:{$this->seed}]", + $text + ); + } + + // Simple tags + public function parseSimple($text) + { + // Parse all simple tags + foreach ($this->simple as $code) { + $text = preg_replace( + "#\[{$code}](.*?)\[/{$code}\]#s", + "[{$code}:{$this->seed}]\\1[/{$code}:{$this->seed}]", + $text + ); + } + return $text; + } + + // Code tag + public function parseCode($text) + { + $text = preg_replace_callback( + "#\[code\](((?R)|.)*?)\[/code\]#s", + function ($t) { + $escaped = $this->escape($t[1]); + + return "[code:{$this->seed}]{$escaped}[/code:{$this->seed}]"; + }, + $text + ); + + return $text; + } + + // Quote tag + public function parseQuote($text) + { + $patterns = ["/\[(quote(?:=".+?")?)\]/", '[/quote]']; + $counts = [preg_match_all($patterns[0], $text), substr_count($text, $patterns[1])]; + $limit = min($counts); + + $text = preg_replace($patterns[0], "[\\1:{$this->seed}]", $text, $limit); + $text = preg_replace('/' . preg_quote($patterns[1], '/') . '/', "[/quote:{$this->seed}]", $text, $limit); + + return $text; + } + + public function parseList($text) + { + $patterns = ["/\[(list(?:=.+?)?)\]/", '[/list]']; + $counts = [preg_match_all($patterns[0], $text), substr_count($text, $patterns[1])]; + $limit = min($counts); + + $text = str_replace('[*]', "[*:{$this->seed}]", $text); + $text = str_replace('[/*]', '', $text); + + $text = preg_replace($patterns[0], "[\\1:{$this->seed}]", $text, $limit); + $text = preg_replace('/' . preg_quote($patterns[1], '/') . '/', "[/list:o:{$this->seed}]", $text, $limit); + + return $text; + } + + public function parseEmotes($text) + { + $match = []; + $replace = []; + + foreach ($this->emoticons as $emote) { + $match[] = '(?<=^|[\n .])' . preg_quote($emote['code'], '#') . '(?![^<>]*>)'; + $replace[] = '' . $emote['code'] . ''; + } + + if (count($match)) { + $text = trim( + preg_replace( + explode( + chr(0), + '#' . implode('#' . chr(0) . '#', $match) . '#' + ), + $replace, + $text + ) + ); + } + + return $text; + } + + public function parseUrl($text) + { + $urlPattern = '(?:https?|ftp)://.+?'; + + $text = preg_replace_callback( + "#\[url\]({$urlPattern})\[/url\]#", + function ($m) { + $url = $this->escape($m[1]); + return "[url:{$this->seed}]{$url}[/url:{$this->seed}]"; + }, + $text + ); + + $text = preg_replace_callback( + "#\[url=({$urlPattern})\](.+?)\[/url\]#", + function ($m) { + $url = $this->escape($m[1]); + return "[url={$url}:{$this->seed}]{$m[2]}[/url:{$this->seed}]"; + }, + $text + ); + + return $text; + } + + public function parseLinks($text) + { + // Spaces + $spaces = ["(^|\s)", "((?:\.|\))?(?:$|\s|\n|\r))"]; + + // HTTP(s), FTP, IRC and osu + $text = preg_replace( + "#{$spaces[0]}((?:https?|ftp|irc|osu)://[^\s]+?){$spaces[1]}#", + "\\1\\2\\3", + $text + ); + + // Prefixed with www. + $text = preg_replace( + "/{$spaces[0]}(www\.[^\s]+){$spaces[1]}/", + "\\1\\2\\3", + $text + ); + + // E-mail addresses + $text = preg_replace( + "/{$spaces[0]}([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z-]+){$spaces[1]}/", + "\\1\\2\\3", + $text + ); + + return $text; + } + + // Escapes + public function escape($text) + { + return str_replace( + array_keys($this->escapes), + $this->escapes, + $text + ); + } + + // Generator + public function generate() + { + // Get the text + $text = htmlentities($this->text); + + $text = $this->parseCode($text); + $text = $this->parseQuote($text); + $text = $this->parseList($text); + + $text = $this->parseSimple($text); + $text = $this->parseAlign($text); + $text = $this->parseUrl($text); + $text = $this->parseSize($text); + $text = $this->parseColour($text); + + $text = $this->parseLinks($text); + + return $text; + } +} diff --git a/_sakura/components/Forum/Post.php b/_sakura/components/Forum/Post.php index 3087296..0726b87 100644 --- a/_sakura/components/Forum/Post.php +++ b/_sakura/components/Forum/Post.php @@ -8,6 +8,7 @@ namespace Sakura\Forum; use Sakura\Main; use Sakura\Database; use Sakura\User; +use Sakura\BBcode\BBcode; /** * Class Post diff --git a/_sakura/components/User.php b/_sakura/components/User.php index f2095e9..bbdaea9 100755 --- a/_sakura/components/User.php +++ b/_sakura/components/User.php @@ -704,7 +704,7 @@ class User ], ['change_id', true]); // Check if anything was returned - if ($getOld) { + if ($getOld && $getOld['user_id'] != $this->id()) { return [0, 'TOO_RECENT', $getOld['change_time']]; } diff --git a/_sakura/sakura.php b/_sakura/sakura.php index 851041c..174b310 100755 --- a/_sakura/sakura.php +++ b/_sakura/sakura.php @@ -8,7 +8,7 @@ namespace Sakura; // Define Sakura version -define('SAKURA_VERSION', '20151122'); +define('SAKURA_VERSION', '20151125'); define('SAKURA_VLABEL', 'Eminence'); define('SAKURA_COLOUR', '#6C3082'); define('SAKURA_STABLE', false); @@ -50,6 +50,9 @@ require_once ROOT . '_sakura/components/Urls.php'; require_once ROOT . '_sakura/components/User.php'; require_once ROOT . '_sakura/components/Users.php'; require_once ROOT . '_sakura/components/Whois.php'; +require_once ROOT . '_sakura/components/BBcode/BBcode.php'; +require_once ROOT . '_sakura/components/BBcode/Parse.php'; +require_once ROOT . '_sakura/components/BBcode/Store.php'; require_once ROOT . '_sakura/components/Forum/Forum.php'; require_once ROOT . '_sakura/components/Forum/Forums.php'; require_once ROOT . '_sakura/components/Forum/Post.php';