summary refs log tree commit diff
diff options
context:
space:
mode:
authorNakidai <nakidai@disroot.org>2026-02-07 15:08:54 +0300
committerNakidai <nakidai@disroot.org>2026-02-07 15:13:01 +0300
commit643b1b995679d9ea315d5767111f376c5af6c44b (patch)
treefb3a320dfb77c260b26f913bac924a0a75c9605b
parente6aff7291f742cf3a435b8103f98699eab75c948 (diff)
downloadlibreircd-643b1b995679d9ea315d5767111f376c5af6c44b.tar.gz
libreircd-643b1b995679d9ea315d5767111f376c5af6c44b.zip
Refactor MODE
MODE command is used to manage modes of both users and channels. But
since these tasks are quite different it'd be nice to split them to
not have an if statement whose both branches occupe whole function
-rw-r--r--handle.c28
-rw-r--r--reply.c5
2 files changed, 29 insertions, 4 deletions
diff --git a/handle.c b/handle.c
index c825ec6..31a11c1 100644
--- a/handle.c
+++ b/handle.c
@@ -74,12 +74,19 @@ join(struct Message *msg, struct Peer *peer)
 }
 
 static int
-mode(struct Message *msg, struct Peer *peer)
+mode_channel(struct Message *msg, struct Peer *peer)
+{
+	(void)msg;
+	(void)peer;
+	return 0;
+}
+
+static int
+mode_peer(struct Message *msg, struct Peer *peer)
 {
 	int set = 1, m;
 
-	ensure(peer->type, reply(peer, 451), 0);
-	ensure(msg->params[0] && *msg->params[0], reply(peer, 431), 0);
+	ensure(!strcmp(msg->params[0], peer->nick), reply(peer, 502, msg->params[0]), 0);
 	ensure(msg->params[1] && *msg->params[1], reply(peer, 221), 0);
 
 	switch (*msg->params[1])
@@ -104,7 +111,7 @@ mode(struct Message *msg, struct Peer *peer)
 
 			if (set && !(m & (OPER | LOCALOPER)))
 				peer->modes |= m;
-			else if (!(m & RESTRICTED))
+			else if (!set && !(m & RESTRICTED))
 				peer->modes &= ~m;
 		}
 	}
@@ -114,6 +121,19 @@ mode(struct Message *msg, struct Peer *peer)
 }
 
 static int
+mode(struct Message *msg, struct Peer *peer)
+{
+	ensure(peer->type, reply(peer, 451), 0);
+	ensure(msg->params[0] && *msg->params[0], reply(peer, 431), 0);
+
+	switch (*msg->params[0])
+	{
+	break; case '#': case '!': case '+': case '&': return mode_channel(msg, peer);
+	break; default: return mode_peer(msg, peer);
+	}
+}
+
+static int
 names(struct Message *msg, struct Peer *peer)
 {
 	static char buf[MESSAGE_MAX];
diff --git a/reply.c b/reply.c
index c5609e9..04a00c2 100644
--- a/reply.c
+++ b/reply.c
@@ -263,6 +263,11 @@ vreply(const struct Peer *peer, int number, va_list ap)
 		getnick(peer),
 		*m
 	), m, _);
+	REPLY(502, WRITE(
+		":%s 502 %s :Cannot change mode for other users",
+		hostname,
+		getnick(peer)
+	), _);
 	default: warn("unknown reply: %d", number); return WRITE(
 		":%s 421 %s err :Reply %d is not implemented yet",
 		hostname,