Count UTF-8 bytes and graphemes instead Microsoft brand UTF-16 whatevers.

This commit is contained in:
flash 2025-04-14 21:57:24 +00:00
parent 306f8a29d1
commit e7b38dc8e1
Signed by: flash
GPG key ID: 2C9C2C574D47FE3E
9 changed files with 52 additions and 15 deletions

View file

@ -1,5 +1,7 @@
using System;
using System.Globalization;
using System.Text;
using SharpChat.Commands;
namespace SharpChat {
public class ChatUser : IEquatable<ChatUser> {
@ -23,8 +25,15 @@ namespace SharpChat {
get {
StringBuilder sb = new();
if(Status == ChatUserStatus.Away)
sb.AppendFormat("&lt;{0}&gt;_", StatusText[..Math.Min(StatusText.Length, 5)].ToUpperInvariant());
if(Status == ChatUserStatus.Away) {
string statusText = StatusText.Trim();
StringInfo sti = new StringInfo(statusText);
if(Encoding.UTF8.GetByteCount(statusText) > AFKCommand.MAX_BYTES
|| sti.LengthInTextElements > AFKCommand.MAX_GRAPHEMES)
statusText = sti.SubstringByTextElements(0, AFKCommand.MAX_GRAPHEMES);
sb.AppendFormat("&lt;{0}&gt;_", statusText.ToUpperInvariant());
}
sb.Append(LegacyName);

View file

@ -1,10 +1,13 @@
using SharpChat.Packet;
using System.Globalization;
using System.Linq;
using System.Text;
namespace SharpChat.Commands {
public class AFKCommand : IChatCommand {
private const string DEFAULT = "AFK";
private const int MAX_LENGTH = 5;
public const int MAX_GRAPHEMES = 5;
public const int MAX_BYTES = MAX_GRAPHEMES * 10;
public bool IsMatch(ChatCommandContext ctx) {
return ctx.NameEquals("afk");
@ -16,8 +19,11 @@ namespace SharpChat.Commands {
statusText = DEFAULT;
else {
statusText = statusText.Trim();
if(statusText.Length > MAX_LENGTH)
statusText = statusText[..MAX_LENGTH].Trim();
StringInfo sti = new StringInfo(statusText);
if(Encoding.UTF8.GetByteCount(statusText) > MAX_BYTES
|| sti.LengthInTextElements > MAX_GRAPHEMES)
statusText = sti.SubstringByTextElements(0, MAX_GRAPHEMES).Trim();
}
ctx.Chat.UpdateUser(

View file

@ -1,8 +1,13 @@
using SharpChat.Packet;
using System.Globalization;
using System.Linq;
using System.Text;
namespace SharpChat.Commands {
public class NickCommand : IChatCommand {
private const int MAX_GRAPHEMES = 16;
private const int MAX_BYTES = MAX_GRAPHEMES * 10;
public bool IsMatch(ChatCommandContext ctx) {
return ctx.NameEquals("nick");
}
@ -36,10 +41,14 @@ namespace SharpChat.Commands {
if(nickStr == targetUser.UserName)
nickStr = string.Empty;
else if(nickStr.Length > 15)
nickStr = nickStr[..15];
else if(string.IsNullOrEmpty(nickStr))
nickStr = string.Empty;
else {
StringInfo nsi = new StringInfo(nickStr);
if(Encoding.UTF8.GetByteCount(nickStr) > MAX_BYTES
|| nsi.LengthInTextElements > MAX_GRAPHEMES)
nickStr = nsi.SubstringByTextElements(0, MAX_GRAPHEMES).Trim();
}
if(!string.IsNullOrWhiteSpace(nickStr) && ctx.Chat.Users.Any(u => u.NameEquals(nickStr))) {
ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.NAME_IN_USE, true, nickStr));

View file

@ -24,6 +24,7 @@ namespace SharpChat.EventStorage {
SslMode = MySqlSslMode.None,
ForceSynchronous = true,
ConnectionTimeout = 5,
DefaultCommandTimeout = 900, // fuck it, 15 minutes
}.ToString();
}

View file

@ -30,6 +30,14 @@ namespace SharpChat.EventStorage {
DoMigration("create_events_table", CreateEventsTable);
DoMigration("allow_null_target", AllowNullTarget);
DoMigration("event_data_as_medium_blob", EventDataAsMediumBlob);
}
private void EventDataAsMediumBlob() {
RunCommand(
"ALTER TABLE `sqc_events`"
+ " CHANGE COLUMN `event_data` `event_data` MEDIUMBLOB NULL DEFAULT NULL AFTER `event_flags`;"
);
}
private void AllowNullTarget() {

View file

@ -5,7 +5,9 @@ using SharpChat.EventStorage;
using SharpChat.Packet;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
namespace SharpChat.PacketHandlers
{
@ -55,8 +57,10 @@ namespace SharpChat.PacketHandlers
ctx.Chat.UpdateUser(user, status: ChatUserStatus.Online);
int maxMsgLength = MaxMessageLength;
if(messageText.Length > maxMsgLength)
messageText = messageText[..maxMsgLength];
StringInfo messageTextInfo = new StringInfo(messageText);
if(Encoding.UTF8.GetByteCount(messageText) > (maxMsgLength * 10)
|| messageTextInfo.LengthInTextElements > maxMsgLength)
messageText = messageTextInfo.SubstringByTextElements(0, maxMsgLength);
messageText = messageText.Trim();

View file

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
</PropertyGroup>
<ItemGroup>

View file

@ -86,10 +86,11 @@ namespace SharpChat {
return;
}
if(EnabledSslProtocols == SslProtocols.None) {
EnabledSslProtocols = SslProtocols.Tls;
FleckLog.Debug("Using default TLS 1.0 security protocol.");
}
// makes dotnet shut up, TLS is handled by NGINX anyway
// if(EnabledSslProtocols == SslProtocols.None) {
// EnabledSslProtocols = SslProtocols.Tls;
// FleckLog.Debug("Using default TLS 1.0 security protocol.");
// }
}
ListenForClients();
_config = config;

View file

@ -10,5 +10,4 @@ namespace SharpChat {
=> ((DateTimeOffset.Now.ToUnixTimeMilliseconds() - EPOCH) << 8)
| (ushort)(Interlocked.Increment(ref Counter) & 0xFFFF);
}
}