diff --git a/.gitignore b/.gitignore
index 512069a..eefe962 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,7 @@ $RECYCLE.BIN/
# Compiled/copied assets
/public/js
/public/css
+
+# User assets
+/uploads/*
+!/uploads/.gitkeep
diff --git a/app/BBcode.php b/app/BBcode.php
index 7b7747f..b5b5235 100644
--- a/app/BBcode.php
+++ b/app/BBcode.php
@@ -16,25 +16,133 @@ namespace Sakura;
class BBcode
{
/**
- * BBcodes, also for backwards compatibility.
+ * Holds the bbcode parsers
*
* @var array
*/
- protected static $bbcodes = [];
-
- /**
- * Initialiser.
- */
- public static function init()
- {
- }
+ public static $parsers = [
+ 'bold' => [
+ 'pattern' => '/\[b\](.*?)\[\/b\]/s',
+ 'replace' => '$1',
+ 'content' => '$1',
+ ],
+ 'italic' => [
+ 'pattern' => '/\[i\](.*?)\[\/i\]/s',
+ 'replace' => '$1',
+ 'content' => '$1',
+ ],
+ 'underline' => [
+ 'pattern' => '/\[u\](.*?)\[\/u\]/s',
+ 'replace' => '$1',
+ 'content' => '$1',
+ ],
+ 'linethrough' => [
+ 'pattern' => '/\[s\](.*?)\[\/s\]/s',
+ 'replace' => '$1',
+ 'content' => '$1',
+ ],
+ 'header' => [
+ 'pattern' => '/\[header\](.*?)\[\/header\]/s',
+ 'replace' => '
$1', + 'content' => '$1', + ], + 'namedquote' => [ + 'pattern' => '/\[quote\=(.*?)\](.*)\[\/quote\]/s', + 'replace' => '
$1$2', + 'content' => '$2', + ], + 'link' => [ + 'pattern' => '/\[url\](.*?)\[\/url\]/s', + 'replace' => '$1', + 'content' => '$1', + ], + 'namedlink' => [ + 'pattern' => '/\[url\=(.*?)\](.*?)\[\/url\]/s', + 'replace' => '$2', + 'content' => '$2', + ], + 'image' => [ + 'pattern' => '/\[img\](.*?)\[\/img\]/s', + 'replace' => '', + 'content' => '$1', + ], + 'orderedlistnumerical' => [ + 'pattern' => '/\[list=1\](.*?)\[\/list\]/s', + 'replace' => '
$1
',
+ 'content' => '$1',
+ ],
+ 'youtube' => [
+ 'pattern' => '/\[youtube\](.*?)\[\/youtube\]/s',
+ 'replace' => '',
+ 'content' => '$1',
+ ],
+ 'linebreak' => [
+ 'pattern' => '/\r\n|\r|\n/',
+ 'replace' => ' tags.
- * See if this can be deprecated with a custom implementation!
- *
- * @param string $text Dirty
- *
- * @return string Clean
- */
- public static function fixCodeTags($text)
- {
- $parts = explode('', $text);
- $newStr = '';
-
- if (count($parts) > 1) {
- foreach ($parts as $p) {
- $parts2 = explode('
', $p);
- if (count($parts2) > 1) {
- $code = str_replace('
', '', $parts2[0]);
- $code = str_replace('
', '', $code);
- $code = str_replace('
', '', $code);
- $code = str_replace('<', '<', $code);
- $newStr .= '' . $code . '
';
- $newStr .= $parts2[1];
- } else {
- $newStr .= $p;
- }
- }
- } else {
- $newStr = $text;
+ foreach (self::$parsers as $parser) {
+ $text = preg_replace($parser['pattern'], $parser['replace'], $text);
}
- return $newStr;
+ return $text;
}
}
diff --git a/app/Controllers/Settings/AppearanceController.php b/app/Controllers/Settings/AppearanceController.php
index f81827a..4131518 100644
--- a/app/Controllers/Settings/AppearanceController.php
+++ b/app/Controllers/Settings/AppearanceController.php
@@ -84,7 +84,7 @@ class AppearanceController extends Controller
$userId = ActiveUser::$user->id;
$ext = image_type_to_extension($meta[2]);
- $filename = "{$mode}_{$userId}.{$ext}";
+ $filename = "{$mode}_{$userId}{$ext}";
// Create the file
$file = File::create(file_get_contents($tmpName), $filename, ActiveUser::$user);
@@ -106,7 +106,11 @@ class AppearanceController extends Controller
public function deleteFile($mode)
{
- (new File(ActiveUser::$user->{$mode}))->delete();
+ $fileId = ActiveUser::$user->{$mode};
+
+ if ($fileId) {
+ (new File($fileId))->delete();
+ }
}
public function avatar()
diff --git a/app/File.php b/app/File.php
index f688837..aeaf855 100644
--- a/app/File.php
+++ b/app/File.php
@@ -84,13 +84,15 @@ class File
$id = DB::table('uploads')
->insertGetId([
'user_id' => $user->id,
- 'file_data' => $data,
'file_name' => $name,
'file_mime' => $mime,
'file_time' => time(),
'file_expire' => $expire,
]);
+ // Save the file data
+ file_put_contents(config('file.uploads_dir') . $id . ".bin", $data);
+
// Return a new File object
return new File($id);
}
@@ -112,7 +114,7 @@ class File
$fileRow = $fileRow[0];
$this->id = $fileRow->file_id;
$this->user = User::construct($fileRow->user_id);
- $this->data = $fileRow->file_data;
+ $this->data = file_get_contents(config('file.uploads_dir') . $fileRow->file_id . ".bin");
$this->name = $fileRow->file_name;
$this->mime = $fileRow->file_mime;
$this->time = $fileRow->file_time;
@@ -125,6 +127,8 @@ class File
*/
public function delete()
{
+ unlink(config('file.uploads_dir') . $this->id . ".bin");
+
DB::table('uploads')
->where('file_id', $this->id)
->delete();
diff --git a/app/User.php b/app/User.php
index 8b76ea7..ba01ed0 100644
--- a/app/User.php
+++ b/app/User.php
@@ -7,6 +7,7 @@
namespace Sakura;
+use Carbon\Carbon;
use Sakura\Perms;
use Sakura\Perms\Site;
use stdClass;
@@ -428,6 +429,26 @@ class User
$this->permissions = new Perms(Perms::SITE);
}
+ /**
+ * Get a Carbon object of the registration date
+ *
+ * @return Carbon
+ */
+ public function registerDate()
+ {
+ return Carbon::createFromTimestamp($this->registered);
+ }
+
+ /**
+ * Get a Carbon object of the last online date
+ *
+ * @return Carbon
+ */
+ public function lastDate()
+ {
+ return Carbon::createFromTimestamp($this->lastOnline);
+ }
+
/**
* Get the user's birthday.
*
diff --git a/config/config.example.ini b/config/config.example.ini
index 6f77bea..9dbb697 100644
--- a/config/config.example.ini
+++ b/config/config.example.ini
@@ -15,7 +15,8 @@
; ; sqlite
; driver = sqlite
; database = sakura.sq3
-; prefix = sakura_
+; ; Although the option exists, setting a table prefix for sqlite breaks some migration related things.
+; prefix =
; ; postgres
; driver = pgsql
@@ -54,6 +55,9 @@ maintenance = false
; URL of the sakurako chat (full path) without trailing slash
chat = http://chat.localghost
+; Date formatting string
+date_format = D Y-m-d H:i:s T
+
; Cookie settings
[cookie]
prefix = sakura_
@@ -103,7 +107,7 @@ secure = tls
; File settings
[file]
-upload_dir = uploads/
+uploads_dir = uploads/
; Avatar requirements
[file.avatar]
diff --git a/database/2016_08_04_175711_files_belong_on_the_filesystem.php b/database/2016_08_04_175711_files_belong_on_the_filesystem.php
new file mode 100644
index 0000000..f552a3d
--- /dev/null
+++ b/database/2016_08_04_175711_files_belong_on_the_filesystem.php
@@ -0,0 +1,35 @@
+table('uploads', function (Blueprint $table) {
+ $table->dropColumn('file_data');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ $schema = DB::getSchemaBuilder();
+
+ $schema->table('uploads', function (Blueprint $table) {
+ $table->binary('file_data');
+ });
+ }
+}
diff --git a/resources/assets/typescript/Sakura/Changelog.ts b/resources/assets/typescript/Sakura/Changelog.ts
index c8a90ee..8ac8749 100644
--- a/resources/assets/typescript/Sakura/Changelog.ts
+++ b/resources/assets/typescript/Sakura/Changelog.ts
@@ -28,7 +28,7 @@ namespace Sakura
title.style.marginBottom = '1px';
link.innerText = 'Changelog';
- link.href = Config.ChangelogUrl + '#r' + Config.Revision;
+ link.href = Config.ChangelogUrl;
link.target = '_blank';
DOM.Append(title, link);
diff --git a/resources/assets/typescript/Sakura/Config.ts b/resources/assets/typescript/Sakura/Config.ts
index 93396fe..f095bae 100644
--- a/resources/assets/typescript/Sakura/Config.ts
+++ b/resources/assets/typescript/Sakura/Config.ts
@@ -2,7 +2,6 @@ namespace Sakura
{
export class Config
{
- public static Revision: number = 0;
public static UserId: number = 0;
public static SessionId: string = "";
public static LoggedIn: boolean = false;
diff --git a/resources/views/aitemu/user/profile.twig b/resources/views/aitemu/user/profile.twig
index 9fbf395..21fb018 100644
--- a/resources/views/aitemu/user/profile.twig
+++ b/resources/views/aitemu/user/profile.twig
@@ -106,8 +106,8 @@
{{ profile.username }}
- Joined {# $user->joined()->format('r') #}
- Last seen {# $user->lastSeen()->format('r') #}
+ Joined {{ profile.registerDate.format('r') }}
+ Last seen {{ profile.lastDate.format('r') }}
{% endblock %}
diff --git a/resources/views/yuuno/elements/indexPanel.twig b/resources/views/yuuno/elements/indexPanel.twig
index 4c69eda..62cbc8d 100644
--- a/resources/views/yuuno/elements/indexPanel.twig
+++ b/resources/views/yuuno/elements/indexPanel.twig
@@ -20,7 +20,7 @@
All active users in the past 2 minutes
{% for amount,onlineUser in stats.onlineUsers %}
- {{ onlineUser.username }}
+ {{ onlineUser.username }}
{% endfor %}
{% else %}
diff --git a/resources/views/yuuno/elements/newsPost.twig b/resources/views/yuuno/elements/newsPost.twig
index bb09206..4669642 100644
--- a/resources/views/yuuno/elements/newsPost.twig
+++ b/resources/views/yuuno/elements/newsPost.twig
@@ -12,6 +12,6 @@
- Posted
+ Posted
{% if newsHideCommentCount is not defined %}{{ post.commentCount }} comment{% if post.commentCount != 1 %}s{% endif %}{% endif %}
diff --git a/resources/views/yuuno/forum/elements/forumEntry.twig b/resources/views/yuuno/forum/elements/forumEntry.twig
index e80b7c3..b406bac 100644
--- a/resources/views/yuuno/forum/elements/forumEntry.twig
+++ b/resources/views/yuuno/forum/elements/forumEntry.twig
@@ -24,7 +24,7 @@
{% if forum.lastPost.id %}
{{ forum.lastPost.subject|slice(0, 30) }}{% if forum.lastPost.subject|length > 30 %}...{% endif %}
- by {% if forum.lastPost.poster.id %}{{ forum.lastPost.poster.username }}{% else %}[deleted user]{% endif %}
+ by {% if forum.lastPost.poster.id %}{{ forum.lastPost.poster.username }}{% else %}[deleted user]{% endif %}
{% else %}
There are no posts in this forum.
{% endif %}
diff --git a/resources/views/yuuno/forum/elements/topicEntry.twig b/resources/views/yuuno/forum/elements/topicEntry.twig
index dbe87ec..cf8b979 100644
--- a/resources/views/yuuno/forum/elements/topicEntry.twig
+++ b/resources/views/yuuno/forum/elements/topicEntry.twig
@@ -22,6 +22,6 @@
{% else %}
[deleted user]
{% endif %}
-
+
diff --git a/resources/views/yuuno/forum/index.twig b/resources/views/yuuno/forum/index.twig
index 05c4734..c1d6ee5 100644
--- a/resources/views/yuuno/forum/index.twig
+++ b/resources/views/yuuno/forum/index.twig
@@ -17,7 +17,7 @@
{{ _t.title }}
-
+
{% endfor %}
@@ -36,7 +36,7 @@
by
{{ _p.poster.username }}
-
+
{% endfor %}
@@ -48,7 +48,7 @@
- {{ activePoster.username }}
+ {{ activePoster.username }}
{% if activePoster.isPremium %} {% endif %} {{ activePoster.title }}
diff --git a/resources/views/yuuno/forum/topic.twig b/resources/views/yuuno/forum/topic.twig
index f44120d..4da5e3e 100644
--- a/resources/views/yuuno/forum/topic.twig
+++ b/resources/views/yuuno/forum/topic.twig
@@ -111,7 +111,7 @@
{{ post.subject|slice(0, 50) }}{% if post.subject|length > 50 %}...{% endif %}
diff --git a/resources/views/yuuno/master.twig b/resources/views/yuuno/master.twig
index b95c897..b3376a8 100644
--- a/resources/views/yuuno/master.twig
+++ b/resources/views/yuuno/master.twig
@@ -112,23 +112,23 @@