mirror of
https://github.com/BillyOutlast/UNIT3D.git
synced 2026-02-04 03:01:20 +01:00
Merge pull request #3222 from Roardom/bbcode-improvements
(Update) Remove XSS cleaner and remove XSS vulnerabilities
This commit is contained in:
@@ -153,7 +153,7 @@ class Bbcode
|
||||
'block' => true,
|
||||
],
|
||||
'namedquote' => [
|
||||
'openBbcode' => '/^\[quote=([^<>"]*?)\]/i',
|
||||
'openBbcode' => '/^\[quote=(.*?)\]/i',
|
||||
'closeBbcode' => '[/quote]',
|
||||
'openHtml' => '<blockquote><i class="fas fa-quote-left"></i> <cite>Quoting $1:</cite><p>',
|
||||
'closeHtml' => '</p></blockquote>',
|
||||
@@ -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('[*]', '<li>', (string) $source);
|
||||
$source = str_replace('[hr]', '<hr>', $source);
|
||||
@@ -320,7 +323,7 @@ class Bbcode
|
||||
$source ?? ''
|
||||
);
|
||||
$source = preg_replace_callback(
|
||||
'/\[video="youtube"]([a-z0-9_-]{11})\[\/video]/i',
|
||||
'/\[video="youtube"]([a-z0-9_-]{11})\[\/video]/i',
|
||||
static fn ($matches) => '<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/'.$matches[1].'?rel=0" allow="autoplay; encrypted-media" allowfullscreen></iframe>',
|
||||
$source ?? ''
|
||||
);
|
||||
|
||||
@@ -27,7 +27,14 @@ class Linkify
|
||||
$validator = new Validator(
|
||||
false, // bool - if should use top level domain to match urls without scheme
|
||||
[], // string[] - array of blacklisted schemes
|
||||
[], // string[] - array of whitelisted schemes
|
||||
[
|
||||
'http',
|
||||
'https',
|
||||
'irc',
|
||||
'ftp',
|
||||
'sftp',
|
||||
'magnet',
|
||||
], // string[] - array of whitelisted schemes
|
||||
true // bool - if should match emails (if match by TLD set to "false" - will match only "mailto" urls)
|
||||
);
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ namespace App\Http\Livewire;
|
||||
|
||||
use App\Helpers\Bbcode;
|
||||
use Livewire\Component;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
class BbcodeInput extends Component
|
||||
{
|
||||
@@ -39,13 +38,13 @@ class BbcodeInput extends Component
|
||||
$this->name = $name;
|
||||
$this->label = $label;
|
||||
$this->isRequired = $required;
|
||||
$this->contentBbcode = $content === null ? (old($name) ?? '') : htmlspecialchars_decode($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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ namespace App\Http\Resources;
|
||||
use App\Helpers\Bbcode;
|
||||
use hdvinnie\LaravelJoyPixels\LaravelJoyPixels;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
/**
|
||||
* @mixin \App\Models\Message
|
||||
@@ -33,17 +32,14 @@ class ChatMessageResource extends JsonResource
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
$emojiOne = app()->make(LaravelJoyPixels::class);
|
||||
$emojiOne = new LaravelJoyPixels();
|
||||
|
||||
$bbcode = new Bbcode();
|
||||
$logger = $bbcode->parse($this->message);
|
||||
$logger = $emojiOne->toImage($logger);
|
||||
|
||||
if ($this->user_id == 1) {
|
||||
$logger = $bbcode->parse('<div class="align-left"><div class="chatTriggers">'.$this->message.'</div></div>');
|
||||
$logger = $emojiOne->toImage($logger);
|
||||
$logger = str_replace('a href="/#', 'a trigger="bot" class="chatTrigger" href="/#', $logger);
|
||||
} else {
|
||||
$logger = $bbcode->parse('<div class="align-left">'.$this->message.'</div>');
|
||||
$logger = $emojiOne->toImage($logger);
|
||||
}
|
||||
|
||||
return [
|
||||
@@ -52,7 +48,7 @@ class ChatMessageResource extends JsonResource
|
||||
'user' => new ChatUserResource($this->whenLoaded('user')),
|
||||
'receiver' => new ChatUserResource($this->whenLoaded('receiver')),
|
||||
'chatroom' => new ChatRoomResource($this->whenLoaded('chatroom')),
|
||||
'message' => (new AntiXSS())->xss_clean($logger),
|
||||
'message' => $logger,
|
||||
'created_at' => $this->created_at->toIso8601String(),
|
||||
'updated_at' => $this->updated_at->toIso8601String(),
|
||||
];
|
||||
|
||||
@@ -21,7 +21,6 @@ use App\Helpers\Linkify;
|
||||
use App\Traits\Auditable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
/**
|
||||
* App\Models\Article.
|
||||
@@ -69,14 +68,6 @@ class Article extends Model
|
||||
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.
|
||||
*/
|
||||
|
||||
@@ -23,7 +23,6 @@ use App\Traits\Auditable;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
/**
|
||||
* App\Models\Comment.
|
||||
@@ -111,14 +110,6 @@ class Comment extends Model
|
||||
$builder->whereNull('parent_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,6 @@ namespace App\Models;
|
||||
use App\Helpers\Bbcode;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
/**
|
||||
* App\Models\Message.
|
||||
@@ -91,14 +90,6 @@ class Message extends Model
|
||||
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.
|
||||
*/
|
||||
|
||||
@@ -20,7 +20,6 @@ use App\Helpers\Linkify;
|
||||
use App\Traits\Auditable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
/**
|
||||
* App\Models\Note.
|
||||
@@ -79,14 +78,6 @@ class Note extends Model
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Message After It's Been Purified.
|
||||
*/
|
||||
public function setMessageAttribute(?string $value): void
|
||||
{
|
||||
$this->attributes['message'] = $value === null ? null : htmlspecialchars((new AntiXSS())->xss_clean($value), ENT_NOQUOTES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Message And Return Valid HTML.
|
||||
*/
|
||||
|
||||
@@ -21,7 +21,6 @@ use App\Helpers\Linkify;
|
||||
use App\Traits\Auditable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
/**
|
||||
* App\Models\Playlist.
|
||||
@@ -78,14 +77,6 @@ class Playlist extends Model
|
||||
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.
|
||||
*/
|
||||
|
||||
@@ -21,7 +21,6 @@ use App\Helpers\Linkify;
|
||||
use App\Traits\Auditable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
/**
|
||||
* App\Models\Post.
|
||||
@@ -156,14 +155,6 @@ class Post extends Model
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -20,7 +20,6 @@ use App\Helpers\Bbcode;
|
||||
use App\Helpers\Linkify;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
/**
|
||||
* App\Models\PrivateMessage.
|
||||
@@ -64,14 +63,6 @@ class PrivateMessage extends Model
|
||||
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.
|
||||
*/
|
||||
|
||||
@@ -18,7 +18,6 @@ namespace App\Models;
|
||||
|
||||
use App\Helpers\Linkify;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
/**
|
||||
* App\Models\TicketNote.
|
||||
@@ -59,14 +58,6 @@ class TicketNote extends Model
|
||||
return $this->belongsTo(Ticket::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Message After It's Been Purified.
|
||||
*/
|
||||
public function setMessageAttribute(?string $value): void
|
||||
{
|
||||
$this->attributes['message'] = $value === null ? null : htmlspecialchars((new AntiXSS())->xss_clean($value), ENT_NOQUOTES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Message And Return Valid HTML.
|
||||
*/
|
||||
|
||||
@@ -29,7 +29,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Laravel\Scout\Searchable;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
/**
|
||||
* App\Models\Torrent.
|
||||
@@ -751,14 +750,6 @@ class Torrent extends Model
|
||||
return $this->hasOne(TorrentTrump::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.
|
||||
*/
|
||||
|
||||
@@ -21,7 +21,6 @@ use App\Helpers\Linkify;
|
||||
use App\Traits\Auditable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
/**
|
||||
* App\Models\TorrentRequest.
|
||||
@@ -215,14 +214,6 @@ class TorrentRequest extends Model
|
||||
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.
|
||||
*/
|
||||
|
||||
@@ -28,7 +28,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Laravel\Fortify\TwoFactorAuthenticatable;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
/**
|
||||
* App\Models\User.
|
||||
@@ -1181,14 +1180,6 @@ class User extends Authenticatable implements MustVerifyEmail
|
||||
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.
|
||||
*/
|
||||
@@ -1199,14 +1190,6 @@ class User extends Authenticatable implements MustVerifyEmail
|
||||
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.
|
||||
*/
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"spatie/ssl-certificate": "^2.6.8",
|
||||
"symfony/dom-crawler": "^6.4.16",
|
||||
"theodorejb/polycast": "dev-master",
|
||||
"voku/anti-xss": "^4.1.42",
|
||||
"vstelmakh/url-highlight": "^3.1.1"
|
||||
},
|
||||
"require-dev": {
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class () extends Migration {
|
||||
public function up(): void
|
||||
{
|
||||
DB::table('articles')
|
||||
->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('comments')
|
||||
->lazyById()
|
||||
->each(function (object $comment): void {
|
||||
/** @var object{id: int, content: string} $comment */
|
||||
DB::table('comments')
|
||||
->where('id', '=', $comment->id)
|
||||
->update([
|
||||
'content' => htmlspecialchars_decode($comment->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('user_notes')
|
||||
->lazyById()
|
||||
->each(function (object $userNote): void {
|
||||
/** @var object{id: int, message: string} $userNote */
|
||||
DB::table('user_notes')
|
||||
->where('id', '=', $userNote->id)
|
||||
->update([
|
||||
'message' => htmlspecialchars_decode($userNote->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('ticket_notes')
|
||||
->lazyById()
|
||||
->each(function (object $ticketNote): void {
|
||||
/** @var object{id: int, message: string} $ticketNote */
|
||||
DB::table('ticket_notes')
|
||||
->where('id', '=', $ticketNote->id)
|
||||
->update([
|
||||
'message' => htmlspecialchars_decode($ticketNote->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),
|
||||
]);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -470,11 +470,6 @@ parameters:
|
||||
count: 1
|
||||
path: app/Http/Resources/ChatMessageResource.php
|
||||
|
||||
-
|
||||
message: "#^Unable to resolve the template type TXssCleanInput in call to method voku\\\\helper\\\\AntiXSS\\:\\:xss_clean\\(\\)$#"
|
||||
count: 1
|
||||
path: app/Http/Resources/ChatMessageResource.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Http\\\\Resources\\\\ChatRoomResource\\:\\:toArray\\(\\) return type has no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
|
||||
Reference in New Issue
Block a user