[^[]+)\[/img:{$this->seed}\]#",
+ function ($i) {
+ return "";
+ },
+ $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}]", '- ', $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}]", "{$tag}>", $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[] = '';
+ }
+
+ 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';