summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Janouch <p.janouch@gmail.com>2014-08-02 23:31:41 +0200
committerPřemysl Janouch <p.janouch@gmail.com>2014-08-03 00:57:25 +0200
commit96f4b81182f15a8a209ffe3ad023f67583999e3c (patch)
tree5980fab137c95f38ef1cac9d6a2b7ce7ae477119
parent97f35bedfd333dea7e46b535c8cf9093fecfad11 (diff)
downloadxK-96f4b81182f15a8a209ffe3ad023f67583999e3c.tar.gz
xK-96f4b81182f15a8a209ffe3ad023f67583999e3c.tar.xz
xK-96f4b81182f15a8a209ffe3ad023f67583999e3c.zip
kike: implement LIST
-rw-r--r--src/common.c6
-rw-r--r--src/kike.c53
2 files changed, 56 insertions, 3 deletions
diff --git a/src/common.c b/src/common.c
index 2593cdc..5a505b2 100644
--- a/src/common.c
+++ b/src/common.c
@@ -634,7 +634,7 @@ str_map_iter_init (struct str_map_iter *self, struct str_map *map)
self->link = NULL;
}
-static bool
+static void *
str_map_iter_next (struct str_map_iter *self)
{
struct str_map *map = self->map;
@@ -643,10 +643,10 @@ str_map_iter_next (struct str_map_iter *self)
while (!self->link)
{
if (self->next_index >= map->len)
- return false;
+ return NULL;
self->link = map->map[self->next_index++];
}
- return true;
+ return self->link->data;
}
static uint64_t
diff --git a/src/kike.c b/src/kike.c
index b1f4f62..2a1744e 100644
--- a/src/kike.c
+++ b/src/kike.c
@@ -325,6 +325,8 @@ struct channel
char *key; ///< Channel key
long user_limit; ///< User limit or -1
+ char *topic; ///< Channel topic
+
struct channel_user *users; ///< Channel users
struct str_vector ban_list; ///< Ban list
@@ -347,6 +349,7 @@ channel_free (struct channel *self)
{
free (self->name);
free (self->key);
+ free (self->topic);
struct channel_user *link, *tmp;
for (link = self->users; link; link = tmp)
@@ -627,6 +630,8 @@ enum
IRC_RPL_LUSERME = 255,
IRC_RPL_USERHOST = 302,
+ IRC_RPL_LIST = 322,
+ IRC_RPL_LISTEND = 323,
IRC_RPL_VERSION = 351,
IRC_RPL_MOTD = 372,
IRC_RPL_MOTDSTART = 375,
@@ -662,6 +667,8 @@ static const char *g_default_replies[] =
[IRC_RPL_LUSERME] = ":I have %d clients and %d servers",
[IRC_RPL_USERHOST] = ":%s",
+ [IRC_RPL_LIST] = "%s %d :%s",
+ [IRC_RPL_LISTEND] = ":End of LIST",
[IRC_RPL_VERSION] = "%s.%d %s :%s",
[IRC_RPL_MOTD] = ":- %s",
[IRC_RPL_MOTDSTART] = ":- %s Message of the day - ",
@@ -998,6 +1005,51 @@ irc_handle_privmsg (const struct irc_message *msg, struct client *c)
}
}
+static void
+irc_send_rpl_list (struct client *c, const struct channel *chan)
+{
+ int visible = 0;
+ for (struct channel_user *user = chan->users;
+ user; user = user->next)
+ visible++;
+
+ irc_send_reply (c, IRC_RPL_LIST, chan->name, visible, chan->topic);
+}
+
+static void
+irc_handle_list (const struct irc_message *msg, struct client *c)
+{
+ if (msg->params.len > 1 && !irc_is_this_me (c->ctx, msg->params.vector[1]))
+ {
+ irc_send_reply (c, IRC_ERR_NOSUCHSERVER, msg->params.vector[1]);
+ return;
+ }
+
+ struct channel *chan;
+ if (msg->params.len == 0)
+ {
+ struct str_map_iter iter;
+ str_map_iter_init (&iter, &c->ctx->channels);
+ while ((chan = str_map_iter_next (&iter)))
+ if (!(chan->modes & (IRC_CHAN_MODE_PRIVATE | IRC_CHAN_MODE_SECRET))
+ || client_on_channel (c, chan))
+ irc_send_rpl_list (c, chan);
+ }
+ else
+ {
+ struct str_vector channels;
+ str_vector_init (&channels);
+ split_str_ignore_empty (msg->params.vector[0], ',', &channels);
+ for (size_t i = 0; i < channels.len; i++)
+ if ((chan = str_map_find (&c->ctx->channels, channels.vector[i]))
+ && (!(chan->modes & IRC_CHAN_MODE_SECRET)
+ || client_on_channel (c, chan)))
+ irc_send_rpl_list (c, chan);
+ str_vector_free (&channels);
+ }
+ irc_send_reply (c, IRC_RPL_LISTEND);
+}
+
// -----------------------------------------------------------------------------
struct irc_command
@@ -1028,6 +1080,7 @@ irc_register_handlers (struct server_context *ctx)
{ "VERSION", true, irc_handle_version },
{ "PRIVMSG", true, irc_handle_privmsg },
+ { "LIST", true, irc_handle_list },
};
for (size_t i = 0; i < N_ELEMENTS (message_handlers); i++)