From 3b9852bc482937840cbddfe5d0e5ff6eef0011e5 Mon Sep 17 00:00:00 2001 From: Pantelis Roditis Date: Sat, 13 Jun 2026 14:15:33 +0300 Subject: [PATCH 1/4] add unicode testing text --- .github/unicode-test.bin | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/unicode-test.bin diff --git a/.github/unicode-test.bin b/.github/unicode-test.bin new file mode 100644 index 000000000..8e508f05b --- /dev/null +++ b/.github/unicode-test.bin @@ -0,0 +1,24 @@ +Normal line. + +This line contains a NO-BREAK SPACE between Hello and World: +Hello World + +This line contains a ZERO WIDTH SPACE between Hello and World: +Hello​World + +This line contains a ZERO WIDTH NON-JOINER: +Hello‌World + +This line contains a ZERO WIDTH JOINER: +Hello‍World + +This line contains a WORD JOINER: +Hello⁠World + +The next line contains a LINE SEPARATOR character: +Hello
World + +The next line contains a PARAGRAPH SEPARATOR character: +Hello
World + +End of file. From f4cc418dd22be855958f4b5b9471bd119450007a Mon Sep 17 00:00:00 2001 From: Pantelis Roditis Date: Sat, 13 Jun 2026 14:16:06 +0300 Subject: [PATCH 2/4] empty lines cleanup --- frontend/modules/target/controllers/WriteupController.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/frontend/modules/target/controllers/WriteupController.php b/frontend/modules/target/controllers/WriteupController.php index 0ec6cb78b..e6f6db8a2 100644 --- a/frontend/modules/target/controllers/WriteupController.php +++ b/frontend/modules/target/controllers/WriteupController.php @@ -109,7 +109,6 @@ public function actionSubmit(int $id) return $this->redirect(['default/view','id'=>$id]); } - $headshot=Headshot::findOne(['target_id'=>$id,'player_id'=>Yii::$app->user->id]); if($headshot===null) { @@ -140,9 +139,6 @@ public function actionSubmit(int $id) 'model' => $model, 'headshot'=>$headshot, ]); - - - } /** From e4942e0b82a3ffd68b4fae5bf7ff07d6057d078a Mon Sep 17 00:00:00 2001 From: Pantelis Roditis Date: Sat, 13 Jun 2026 19:31:25 +0300 Subject: [PATCH 3/4] Update validation logic strip problematic unicode characters rework order --- frontend/modules/target/models/Writeup.php | 40 ++++++++++++++++------ 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/frontend/modules/target/models/Writeup.php b/frontend/modules/target/models/Writeup.php index c46f28cb4..dc3caa8cf 100644 --- a/frontend/modules/target/models/Writeup.php +++ b/frontend/modules/target/models/Writeup.php @@ -63,24 +63,44 @@ public function scenarios() public function rules() { return [ + [['content'], 'filter', 'filter' => function ($value) { + if ($value === null || $value === '') { + return null; + } + + $value = str_replace("\r\n", "\n", $value); + $value = str_replace("\r", "", $value); + + $cleaned = preg_replace('/[\x{2028}\x{2029}]/u', "\n", $value); + if ($cleaned !== null && $cleaned !== false) { + $value = $cleaned; + } + + $value = str_replace("\u{00A0}", ' ', $value); + + $cleaned = preg_replace('/[\x{200B}\x{200C}\x{200D}\x{2060}\x{FEFF}\x{00AD}]/u', '', $value); + if ($cleaned !== null && $cleaned !== false) { + $value = $cleaned; + } + + return $value; + }], + + [['approved'], 'default', 'value' => false], + ['formatter', 'default', 'value' => 'text'], + ['language_id', 'default', 'value' => 'en'], + ['status', 'default', 'value' => 'PENDING'], + [['player_id', 'target_id','content'], 'required'], + [['player_id', 'target_id'], 'integer'], [['approved'], 'boolean'], - [['approved'], 'default','value'=>false], - ['formatter', 'default','value'=>'text'], - ['language_id', 'default','value'=>'en'], [['status', 'comment'], 'string'], - [['content'], 'filter', 'filter' => function ($value) { - return str_replace(["\r\n", "\r"], "\n", $value); - }], [['content'], 'filter','filter'=>'trim'], - [['content'], 'string','skipOnEmpty'=>false, 'min'=>'20'], - ['status','default','value'=>'PENDING'], - [['created_at', 'updated_at'], 'safe'], + [['content'], 'string', 'min'=>20], [['player_id'], 'exist', 'skipOnError' => true, 'targetClass' => Player::class, 'targetAttribute' => ['player_id' => 'id']], [['target_id'], 'exist', 'skipOnError' => true, 'targetClass' => Target::class, 'targetAttribute' => ['target_id' => 'id']], [['language_id'], 'exist', 'skipOnError' => true, 'targetClass' => \app\models\Language::class, 'targetAttribute' => ['language_id' => 'id']], - ]; } From 1f50ed99934234838dc2fe1d27d3ac9b0c125673 Mon Sep 17 00:00:00 2001 From: Pantelis Roditis Date: Sat, 13 Jun 2026 19:31:41 +0300 Subject: [PATCH 4/4] add target_metadata_visible sysconfig --- docs/Sysconfig-Keys.md | 1 + .../material/modules/target/views/default/_target_metadata.php | 2 ++ 2 files changed, 3 insertions(+) diff --git a/docs/Sysconfig-Keys.md b/docs/Sysconfig-Keys.md index 38c182d39..67e8b877e 100644 --- a/docs/Sysconfig-Keys.md +++ b/docs/Sysconfig-Keys.md @@ -49,6 +49,7 @@ These are the system configuration keys used by the platform applications. Any k * `stream_player_target_help`: Whether or not to produce stream entries for players who activate writeups on a target. * `log_failed_claims`: Log failed claim attempts? * `team_encrypted_claims_allowed`: Should we allow claims of flags across teams? +* `target_metadata_visible`: Whether or not metadata will be visible to normal players. Admins get to see the metadata no matter this settting. ## String and numeric key/val pairs diff --git a/frontend/themes/material/modules/target/views/default/_target_metadata.php b/frontend/themes/material/modules/target/views/default/_target_metadata.php index 43dd5b127..f4f9f7ed1 100644 --- a/frontend/themes/material/modules/target/views/default/_target_metadata.php +++ b/frontend/themes/material/modules/target/views/default/_target_metadata.php @@ -10,9 +10,11 @@ solution)):?>: formatter->divID = 'markdown-solution'; echo \Yii::$app->formatter->asMarkdown($metadata->solution)?> +sys->target_metadata_visible || Yii::$app->user->identity->isAdmin):?> pre_credits)):?>: formatter->divID = 'markdown-pre-credits'; echo \Yii::$app->formatter->asMarkdown($metadata->pre_credits)?> pre_exploitation)):?>: formatter->divID = 'markdown-pre-exploitation'; echo \Yii::$app->formatter->asMarkdown($metadata->pre_exploitation)?> player_id===Yii::$app->user->id && $target->progress==100) || Yii::$app->user->identity->isAdmin) && !empty($metadata->post_exploitation)):?>: formatter->divID = 'markdown-post-exploitation'; echo \Yii::$app->formatter->asMarkdown($metadata->post_exploitation)?> player_id===Yii::$app->user->id && $target->progress==100) || Yii::$app->user->identity->isAdmin) && !empty($metadata->post_credits)):?>: formatter->divID = 'markdown-post-credits'; echo \Yii::$app->formatter->asMarkdown($metadata->post_credits)?> formatter->divID=$oldId; ?> +