diff --git a/app/Helpers/Bbcode.php b/app/Helpers/Bbcode.php index 03701513a8..e8d2b1245d 100755 --- a/app/Helpers/Bbcode.php +++ b/app/Helpers/Bbcode.php @@ -153,7 +153,7 @@ class Bbcode 'block' => true, ], 'namedquote' => [ - 'openBbcode' => '/^\[quote=([^<>"]*?)\]/i', + 'openBbcode' => '/^\[quote=(.*?)\]/i', 'closeBbcode' => '[/quote]', 'openHtml' => '
Quoting $1:

', 'closeHtml' => '

', @@ -278,6 +278,9 @@ class Bbcode */ public function parse(?string $source, bool $replaceLineBreaks = true): string { + $source ??= ''; + $source = htmlspecialchars($source, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5, 'UTF-8'); + // Replace all void elements since they don't have closing tags $source = str_replace('[*]', '
  • ', (string) $source); $source = preg_replace_callback( @@ -319,7 +322,7 @@ public function parse(?string $source, bool $replaceLineBreaks = true): string $source ?? '' ); $source = preg_replace_callback( - '/\[video="youtube"]([a-z0-9_-]{11})\[\/video]/i', + '/\[video="youtube"]([a-z0-9_-]{11})\[\/video]/i', static fn ($matches) => '', $source ?? '' ); diff --git a/app/Http/Livewire/BbcodeInput.php b/app/Http/Livewire/BbcodeInput.php index 37a6eaf126..4cab5fd4f1 100644 --- a/app/Http/Livewire/BbcodeInput.php +++ b/app/Http/Livewire/BbcodeInput.php @@ -18,7 +18,6 @@ use App\Helpers\Bbcode; use Livewire\Component; -use voku\helper\AntiXSS; class BbcodeInput extends Component { @@ -39,13 +38,13 @@ final public function mount($name, $label, $required = false, $content = null): $this->name = $name; $this->label = $label; $this->isRequired = $required; - $this->contentBbcode = $content === null ? (old($name) ?? '') : htmlspecialchars_decode((string) $content); + $this->contentBbcode = $content ?? old($name) ?? ''; } final public function updatedIsPreviewEnabled(): void { if ($this->isPreviewEnabled) { - $this->contentHtml = (new Bbcode())->parse(htmlspecialchars((new AntiXSS())->xss_clean($this->contentBbcode), ENT_NOQUOTES)); + $this->contentHtml = (new Bbcode())->parse($this->contentBbcode); } } diff --git a/app/Http/Livewire/Comments.php b/app/Http/Livewire/Comments.php index 60cb614a75..bf564f094c 100644 --- a/app/Http/Livewire/Comments.php +++ b/app/Http/Livewire/Comments.php @@ -122,6 +122,7 @@ final public function postComment(): void $comment = $this->model->comments()->create([ 'content' => $this->newCommentState, 'user_id' => auth()->id(), + 'anon' => $this->anon, ]); // New Comment Notification diff --git a/app/Models/Article.php b/app/Models/Article.php index 6e9219adac..7e78c0d2e0 100644 --- a/app/Models/Article.php +++ b/app/Models/Article.php @@ -21,7 +21,6 @@ use App\Traits\Auditable; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use voku\helper\AntiXSS; /** * App\Models\Article. @@ -67,14 +66,6 @@ public function comments(): \Illuminate\Database\Eloquent\Relations\MorphMany return $this->morphMany(Comment::class, 'commentable'); } - /** - * Set The Articles Content After Its Been Purified. - */ - public function setContentAttribute(?string $value): void - { - $this->attributes['content'] = $value === null ? null : htmlspecialchars((new AntiXSS())->xss_clean($value), ENT_NOQUOTES); - } - /** * Parse Content And Return Valid HTML. */ diff --git a/app/Models/Message.php b/app/Models/Message.php index 6ea989cbc0..d7b0a779f7 100644 --- a/app/Models/Message.php +++ b/app/Models/Message.php @@ -19,7 +19,6 @@ use App\Helpers\Bbcode; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use voku\helper\AntiXSS; /** * App\Models\Message. @@ -90,14 +89,6 @@ public function chatroom(): \Illuminate\Database\Eloquent\Relations\BelongsTo return $this->belongsTo(Chatroom::class); } - /** - * Set The Chat Message After Its Been Purified. - */ - public function setMessageAttribute(string $value): void - { - $this->attributes['message'] = htmlspecialchars((new AntiXSS())->xss_clean($value), ENT_NOQUOTES); - } - /** * Parse Content And Return Valid HTML. */ diff --git a/app/Models/Playlist.php b/app/Models/Playlist.php index f1def38904..c87251f9a2 100644 --- a/app/Models/Playlist.php +++ b/app/Models/Playlist.php @@ -21,7 +21,6 @@ use App\Traits\Auditable; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use voku\helper\AntiXSS; /** * App\Models\Playlist. @@ -76,14 +75,6 @@ public function comments(): \Illuminate\Database\Eloquent\Relations\MorphMany return $this->morphMany(Comment::class, 'commentable'); } - /** - * Set The Playlists Description After It's Been Purified. - */ - public function setDescriptionAttribute(?string $value): void - { - $this->attributes['description'] = $value === null ? null : htmlspecialchars((new AntiXSS())->xss_clean($value), ENT_NOQUOTES); - } - /** * Parse Description And Return Valid HTML. */ diff --git a/app/Models/Post.php b/app/Models/Post.php index 6f3cbee02c..073a3ecdff 100644 --- a/app/Models/Post.php +++ b/app/Models/Post.php @@ -21,7 +21,6 @@ use App\Traits\Auditable; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use voku\helper\AntiXSS; /** * App\Models\Post. @@ -154,14 +153,6 @@ public function scopeAuthorized( ); } - /** - * Set The Posts Content After Its Been Purified. - */ - public function setContentAttribute(?string $value): void - { - $this->attributes['content'] = $value === null ? null : htmlspecialchars((new AntiXSS())->xss_clean($value), ENT_NOQUOTES); - } - /** * Parse Content And Return Valid HTML. */ diff --git a/app/Models/PrivateMessage.php b/app/Models/PrivateMessage.php index 2cb09b0ca4..5aba0df11b 100644 --- a/app/Models/PrivateMessage.php +++ b/app/Models/PrivateMessage.php @@ -20,7 +20,6 @@ use App\Helpers\Linkify; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use voku\helper\AntiXSS; /** * App\Models\PrivateMessage. @@ -63,14 +62,6 @@ public function conversation(): \Illuminate\Database\Eloquent\Relations\BelongsT return $this->belongsTo(Conversation::class); } - /** - * Set The PM Message After Its Been Purified. - */ - public function setMessageAttribute(string $value): void - { - $this->attributes['message'] = htmlspecialchars((new AntiXSS())->xss_clean($value), ENT_NOQUOTES); - } - /** * Parse Content And Return Valid HTML. */ diff --git a/app/Models/Torrent.php b/app/Models/Torrent.php index 36ab3d34ac..40f3060d7e 100644 --- a/app/Models/Torrent.php +++ b/app/Models/Torrent.php @@ -29,7 +29,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; -use voku\helper\AntiXSS; /** * App\Models\Torrent. @@ -399,14 +398,6 @@ public function resurrections(): \Illuminate\Database\Eloquent\Relations\HasMany return $this->hasMany(Resurrection::class); } - /** - * Set The Torrents Description After Its Been Purified. - */ - public function setDescriptionAttribute(?string $value): void - { - $this->attributes['description'] = $value === null ? null : htmlspecialchars((new AntiXSS())->xss_clean($value), ENT_NOQUOTES); - } - /** * Parse Description And Return Valid HTML. */ diff --git a/app/Models/TorrentRequest.php b/app/Models/TorrentRequest.php index faf130f8dc..ce3b183de3 100644 --- a/app/Models/TorrentRequest.php +++ b/app/Models/TorrentRequest.php @@ -22,7 +22,6 @@ use App\Traits\TorrentFilter; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use voku\helper\AntiXSS; /** * App\Models\TorrentRequest. @@ -195,14 +194,6 @@ public function claim(): \Illuminate\Database\Eloquent\Relations\HasOne return $this->hasOne(TorrentRequestClaim::class, 'request_id'); } - /** - * Set The Requests Description After Its Been Purified. - */ - public function setDescriptionAttribute(?string $value): void - { - $this->attributes['description'] = $value === null ? null : htmlspecialchars((new AntiXSS())->xss_clean($value), ENT_NOQUOTES); - } - /** * Parse Description And Return Valid HTML. */ diff --git a/app/Models/User.php b/app/Models/User.php index a3fc13e2ff..7098b3e6bb 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -28,7 +28,6 @@ use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Fortify\TwoFactorAuthenticatable; -use voku\helper\AntiXSS; /** * App\Models\User. @@ -1123,14 +1122,6 @@ public function getFormattedBufferAttribute(): string return StringHelper::formatBytes($bytes); } - /** - * Set The Users Signature After It's Been Purified. - */ - public function setSignatureAttribute(?string $value): void - { - $this->attributes['signature'] = $value === null ? null : htmlspecialchars((new AntiXSS())->xss_clean($value), ENT_NOQUOTES); - } - /** * Returns the HTML of the user's signature. */ @@ -1141,14 +1132,6 @@ public function getSignatureHtmlAttribute(): string return (new Linkify())->linky($bbcode->parse($this->signature)); } - /** - * Set The Users About Me After It's Been Purified. - */ - public function setAboutAttribute(?string $value): void - { - $this->attributes['about'] = $value === null ? null : htmlspecialchars((new AntiXSS())->xss_clean($value), ENT_NOQUOTES); - } - /** * Parse About Me And Return Valid HTML. */ diff --git a/composer.json b/composer.json index 04f9121a67..fcde9de33e 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,6 @@ "spatie/ssl-certificate": "^2.6.5", "symfony/dom-crawler": "^6.4.4", "theodorejb/polycast": "dev-master", - "voku/anti-xss": "^4.1.42", "vstelmakh/url-highlight": "^3.0.3" }, "require-dev": { diff --git a/database/migrations/2023_11_04_094036_htmlspecialchars_decode_bbcode.php b/database/migrations/2023_11_04_094036_htmlspecialchars_decode_bbcode.php new file mode 100644 index 0000000000..7c6898767a --- /dev/null +++ b/database/migrations/2023_11_04_094036_htmlspecialchars_decode_bbcode.php @@ -0,0 +1,100 @@ +lazyById() + ->each(function (object $article): void { + /** @var object{id: int, content: string} $article */ + DB::table('articles') + ->where('id', '=', $article->id) + ->update([ + 'content' => htmlspecialchars_decode($article->content), + ]); + }); + + DB::table('messages') + ->lazyById() + ->each(function (object $message): void { + /** @var object{id: int, message: string} $message */ + DB::table('messages') + ->where('id', '=', $message->id) + ->update([ + 'message' => htmlspecialchars_decode($message->message), + ]); + }); + + DB::table('playlists') + ->lazyById() + ->each(function (object $playlist): void { + /** @var object{id: int, description: string} $playlist */ + DB::table('playlists') + ->where('id', '=', $playlist->id) + ->update([ + 'description' => htmlspecialchars_decode($playlist->description), + ]); + }); + + DB::table('posts') + ->lazyById() + ->each(function (object $post): void { + /** @var object{id: int, content: string} $post */ + DB::table('posts') + ->where('id', '=', $post->id) + ->update([ + 'content' => htmlspecialchars_decode($post->content), + ]); + }); + + DB::table('private_messages') + ->lazyById() + ->each(function (object $privateMessage): void { + /** @var object{id: int, message: string} $privateMessage */ + DB::table('private_messages') + ->where('id', '=', $privateMessage->id) + ->update([ + 'message' => htmlspecialchars_decode($privateMessage->message), + ]); + }); + + DB::table('torrents') + ->lazyById() + ->each(function (object $torrent): void { + /** @var object{id: int, description: string} $torrent */ + DB::table('torrents') + ->where('id', '=', $torrent->id) + ->update([ + 'description' => htmlspecialchars_decode($torrent->description), + ]); + }); + + DB::table('requests') + ->lazyById() + ->each(function (object $request): void { + /** @var object{id: int, description: string} $request */ + DB::table('requests') + ->where('id', '=', $request->id) + ->update([ + 'description' => htmlspecialchars_decode($request->description), + ]); + }); + + DB::table('users') + ->lazyById() + ->each(function (object $user): void { + /** @var object{id: int, about: string, signature: string} $user */ + DB::table('users') + ->where('id', '=', $user->id) + ->update([ + 'about' => htmlspecialchars_decode($user->about), + 'signature' => htmlspecialchars_decode($user->signature), + ]); + }); + } +};