summary refs log tree commit diff
path: root/channel.c
diff options
context:
space:
mode:
authorNakidai <nakidai@disroot.org>2026-02-10 03:38:15 +0300
committerNakidai <nakidai@disroot.org>2026-02-10 03:38:15 +0300
commitdb996c22cd51cd46dd9afee1085a8af04cc7b53b (patch)
tree3fdc59fc9f7d42a1e8f96d9ca615e2d8b19a60da /channel.c
parent15b0b805fe2e739c9d89b54e1bfb26beb79c3112 (diff)
downloadlibreircd-db996c22cd51cd46dd9afee1085a8af04cc7b53b.tar.gz
libreircd-db996c22cd51cd46dd9afee1085a8af04cc7b53b.zip
Add channel mode editing support
Well, an oper should have some way to manage their channel :)
Diffstat (limited to 'channel.c')
-rw-r--r--channel.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/channel.c b/channel.c
index 21a777a..d04f3cc 100644
--- a/channel.c
+++ b/channel.c
@@ -79,6 +79,60 @@ channel_exit(struct Channel *channel, struct Peer *peer)
 	return 0;
 }
 
+const struct ChannelModeParam *
+channel_modes_parse(const struct Message *msg)
+{
+	static struct ChannelModeParam modes[MESSAGE_MAX];
+	size_t i, modes_c, queue_l, queue_r;
+	char *m, queue[PARAM_MAX];
+	int set = 1;
+
+	memset(modes, 0, sizeof(modes));
+	for (modes_c = queue_l = queue_r = 0, i = 1; msg->params[i]; ++i, set = 1) switch (*msg->params[i])
+	{
+	case '-':
+		set = 0;
+	case '+':
+	{
+		for (m = msg->params[i]+1; *m; ++m) switch (*m)
+		{
+		break; case 'o':
+			/* since all flags are ASCII (< 128) bit 7
+			 * can be and is abused for the set flag */
+			if (queue_r == lengthof(queue))
+			{
+				modes[modes_c].mode = *m;
+				return modes;
+			}
+			queue[queue_r++] = (set << 7) | *m;
+		break; case 's':
+			modes[modes_c].mode = *m;
+			modes[modes_c++].set = set;
+		break; default:
+			modes[modes_c].mode = *m;
+			modes[modes_c++].set = set;
+			return modes;
+		}
+	} break;
+	default:
+	{
+		modes[modes_c].param = msg->params[i];
+
+		if (queue_l == queue_r)
+		{
+			return modes;
+		}
+		else
+		{
+			modes[modes_c].set = !!(queue[queue_l] & (1 << 7));
+			modes[modes_c++].mode = queue[queue_l++] & ~(1 << 7);
+		}
+	} break;
+	}
+
+	return modes;
+}
+
 void
 channel_remove(size_t cid)
 {