Sanitize text to remove hidden unicode and control characters

This commit is contained in:
LittleSheep 2025-06-07 22:06:57 +08:00
parent a8503735d1
commit 3a978441b6
3 changed files with 41 additions and 4 deletions

View File

@ -1,4 +1,6 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using DysonNetwork.Sphere.Permission; using DysonNetwork.Sphere.Permission;
using DysonNetwork.Sphere.Storage; using DysonNetwork.Sphere.Storage;
@ -142,6 +144,8 @@ public partial class ChatController(AppDatabase db, ChatService cs, ChatRoomServ
public async Task<ActionResult> SendMessage([FromBody] SendMessageRequest request, Guid roomId) public async Task<ActionResult> SendMessage([FromBody] SendMessageRequest request, Guid roomId)
{ {
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
request.Content = TextSanitizer.Sanitize(request.Content);
if (string.IsNullOrWhiteSpace(request.Content) && if (string.IsNullOrWhiteSpace(request.Content) &&
(request.AttachmentsId == null || request.AttachmentsId.Count == 0)) (request.AttachmentsId == null || request.AttachmentsId.Count == 0))
return BadRequest("You cannot send an empty message."); return BadRequest("You cannot send an empty message.");
@ -218,6 +222,8 @@ public partial class ChatController(AppDatabase db, ChatService cs, ChatRoomServ
{ {
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
request.Content = TextSanitizer.Sanitize(request.Content);
var message = await db.ChatMessages var message = await db.ChatMessages
.Include(m => m.Sender) .Include(m => m.Sender)
.Include(m => m.Sender.Account) .Include(m => m.Sender.Account)
@ -230,6 +236,10 @@ public partial class ChatController(AppDatabase db, ChatService cs, ChatRoomServ
if (message.Sender.AccountId != currentUser.Id) if (message.Sender.AccountId != currentUser.Id)
return StatusCode(403, "You can only edit your own messages."); return StatusCode(403, "You can only edit your own messages.");
if (string.IsNullOrWhiteSpace(request.Content) &&
(request.AttachmentsId == null || request.AttachmentsId.Count == 0))
return BadRequest("You cannot send an empty message.");
if (request.RepliedMessageId.HasValue) if (request.RepliedMessageId.HasValue)
{ {
var repliedMessage = await db.ChatMessages var repliedMessage = await db.ChatMessages

View File

@ -3,6 +3,7 @@ using System.Text.Json;
using DysonNetwork.Sphere.Account; using DysonNetwork.Sphere.Account;
using DysonNetwork.Sphere.Permission; using DysonNetwork.Sphere.Permission;
using DysonNetwork.Sphere.Publisher; using DysonNetwork.Sphere.Publisher;
using DysonNetwork.Sphere.Storage;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -149,6 +150,7 @@ public class PostController(
[FromHeader(Name = "X-Pub")] string? publisherName [FromHeader(Name = "X-Pub")] string? publisherName
) )
{ {
request.Content = TextSanitizer.Sanitize(request.Content);
if (string.IsNullOrWhiteSpace(request.Content) && request.Attachments is { Count: 0 }) if (string.IsNullOrWhiteSpace(request.Content) && request.Attachments is { Count: 0 })
return BadRequest("Content is required."); return BadRequest("Content is required.");
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
@ -290,6 +292,7 @@ public class PostController(
[HttpPatch("{id:guid}")] [HttpPatch("{id:guid}")]
public async Task<ActionResult<Post>> UpdatePost(Guid id, [FromBody] PostRequest request) public async Task<ActionResult<Post>> UpdatePost(Guid id, [FromBody] PostRequest request)
{ {
request.Content = TextSanitizer.Sanitize(request.Content);
if (string.IsNullOrWhiteSpace(request.Content) && request.Attachments is { Count: 0 }) if (string.IsNullOrWhiteSpace(request.Content) && request.Attachments is { Count: 0 })
return BadRequest("Content is required."); return BadRequest("Content is required.");
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();

View File

@ -0,0 +1,24 @@
using System.Globalization;
using System.Text;
namespace DysonNetwork.Sphere.Storage;
public abstract class TextSanitizer
{
public static string? Sanitize(string? text)
{
if (string.IsNullOrEmpty(text)) return text;
var filtered = new StringBuilder();
foreach (var ch in from ch in text
let category = CharUnicodeInfo.GetUnicodeCategory(ch)
where category is not (UnicodeCategory.Control or UnicodeCategory.Format
or UnicodeCategory.NonSpacingMark)
select ch)
{
filtered.Append(ch);
}
return filtered.ToString();
}
}