refactor: drop Joda-Time (-> java.time) and make protocol charsets explicit

Modernization following the dependency upgrades:
- Joda-Time was used in exactly one place (ModToolSanctionInfoComposer, to
  subtract probation days from a Date). Migrated to java.time
  (Instant/ZoneId.systemDefault, calendar-accurate like the old Joda call) and
  removed the joda-time dependency entirely — confirmed gone from the shaded jar.
- Make string<->bytes conversions explicitly UTF-8 instead of relying on the
  platform default. Most importantly the wire codec (ClientMessage.readString /
  ServerMessage.appendString) — both sides now pinned to UTF-8 so international
  characters are robust regardless of -Dfile.encoding. Also RCONServerHandler,
  PluginManager and the WS origin-forbidden response.

Verified: clean compile, 15/15 tests, shaded jar.
This commit is contained in:
simoleo89
2026-06-09 16:27:37 +00:00
parent 62104596ac
commit b6ee400b83
7 changed files with 14 additions and 15 deletions
-7
View File
@@ -163,13 +163,6 @@
<version>2.4.3</version>
</dependency>
<!-- Joda Time -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.14.2</version>
</dependency>
<!-- jBCrypt used by the built-in /api/auth/* HTTP login handler
to verify Laravel-style $2y$ BCrypt hashes from users.password -->
<dependency>
@@ -4,6 +4,8 @@ import com.eu.habbo.util.PacketUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.nio.charset.StandardCharsets;
public class ClientMessage {
private final int header;
private final ByteBuf buffer;
@@ -71,7 +73,7 @@ public class ClientMessage {
}
byte[] data = new byte[length];
this.buffer.readBytes(data);
return new String(data);
return new String(data, StandardCharsets.UTF_8);
} catch (Exception e) {
return "";
}
@@ -7,6 +7,7 @@ import io.netty.buffer.ByteBufOutputStream;
import io.netty.buffer.Unpooled;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class ServerMessage {
@@ -61,7 +62,7 @@ public class ServerMessage {
}
try {
byte[] data = obj.getBytes();
byte[] data = obj.getBytes(StandardCharsets.UTF_8);
this.stream.writeShort(data.length);
this.stream.write(data);
} catch (IOException e) {
@@ -9,8 +9,8 @@ import com.eu.habbo.messages.ServerMessage;
import com.eu.habbo.messages.outgoing.MessageComposer;
import com.eu.habbo.messages.outgoing.Outgoing;
import gnu.trove.map.hash.THashMap;
import org.joda.time.DateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
@@ -47,7 +47,10 @@ public class ModToolSanctionInfoComposer extends MessageComposer {
if (item.probationTimestamp > 0) {
probationEndTime = new Date((long) item.probationTimestamp * 1000);
probationStartTime = new DateTime(probationEndTime).minusDays(modToolSanctions.getProbationDays(modToolSanctionLevelItem)).toDate();
probationStartTime = Date.from(probationEndTime.toInstant()
.atZone(ZoneId.systemDefault())
.minusDays(modToolSanctions.getProbationDays(modToolSanctionLevelItem))
.toInstant());
Date tradeLockedUntil = null;
@@ -54,7 +54,7 @@ public class WebSocketHttpHandler extends ChannelInboundHandlerAdapter {
FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1,
HttpResponseStatus.FORBIDDEN,
Unpooled.wrappedBuffer("Origin forbidden".getBytes())
Unpooled.wrappedBuffer("Origin forbidden".getBytes(java.nio.charset.StandardCharsets.UTF_8))
);
response.headers().set("Vary", "Origin");
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
@@ -41,7 +41,7 @@ public class RCONServerHandler extends ChannelInboundHandlerAdapter {
byte[] d = new byte[data.readableBytes()];
data.getBytes(0, d);
String message = new String(d);
String message = new String(d, java.nio.charset.StandardCharsets.UTF_8);
Gson gson = GSON;
String response = "ERROR";
String key = "";
@@ -56,7 +56,7 @@ public class RCONServerHandler extends ChannelInboundHandlerAdapter {
e.printStackTrace();
}
ChannelFuture f = ctx.channel().write(Unpooled.copiedBuffer(response.getBytes()), ctx.channel().voidPromise());
ChannelFuture f = ctx.channel().write(Unpooled.copiedBuffer(response.getBytes(java.nio.charset.StandardCharsets.UTF_8)), ctx.channel().voidPromise());
ctx.channel().flush();
ctx.flush();
f.channel().close();
@@ -277,7 +277,7 @@ public class PluginManager {
byte[] content = new byte[stream.available()];
if (stream.read(content) > 0) {
String body = new String(content);
String body = new String(content, java.nio.charset.StandardCharsets.UTF_8);
HabboPluginConfiguration pluginConfigurtion = PLUGIN_GSON.fromJson(body, HabboPluginConfiguration.class);